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
signature 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;...@@ -8,7 +8,6 @@ const assert = std.debug.assert;
8const fs = std.fs;8const fs = std.fs;
9const leb = std.leb;9const leb = std.leb;
10const log = std.log.scoped(.link);10const log = std.log.scoped(.link);
11const wasm = std.wasm;
1211
13const Atom = @import("Wasm/Atom.zig");12const Atom = @import("Wasm/Atom.zig");
14const Dwarf = @import("Dwarf.zig");13const Dwarf = @import("Dwarf.zig");
...@@ -106,17 +105,17 @@ dwarf: ?Dwarf = null,...@@ -106,17 +105,17 @@ dwarf: ?Dwarf = null,
106105
107// Output sections106// Output sections
108/// Output type section107/// Output type section
109func_types: std.ArrayListUnmanaged(wasm.Type) = .{},108func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{},
110/// Output function section where the key is the original109/// Output function section where the key is the original
111/// function index and the value is function.110/// function index and the value is function.
112/// This allows us to map multiple symbols to the same function.111/// 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) = .{},
114/// Output global section113/// Output global section
115wasm_globals: std.ArrayListUnmanaged(wasm.Global) = .{},114wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},
116/// Memory section115/// Memory section
117memories: wasm.Memory = .{ .limits = .{ .min = 0, .max = null } },116memories: std.wasm.Memory = .{ .limits = .{ .min = 0, .max = null } },
118/// Output table section117/// Output table section
119tables: std.ArrayListUnmanaged(wasm.Table) = .{},118tables: std.ArrayListUnmanaged(std.wasm.Table) = .{},
120/// Output export section119/// Output export section
121exports: std.ArrayListUnmanaged(types.Export) = .{},120exports: std.ArrayListUnmanaged(types.Export) = .{},
122121
...@@ -203,39 +202,39 @@ pub const SymbolLoc = struct {...@@ -203,39 +202,39 @@ pub const SymbolLoc = struct {
203 file: ?u16,202 file: ?u16,
204203
205 /// From a given location, returns the corresponding symbol in the wasm binary204 /// From a given location, returns the corresponding symbol in the wasm binary
206 pub fn getSymbol(self: SymbolLoc, wasm_bin: *const Wasm) *Symbol {205 pub fn getSymbol(loc: SymbolLoc, wasm_bin: *const Wasm) *Symbol {
207 if (wasm_bin.discarded.get(self)) |new_loc| {206 if (wasm_bin.discarded.get(loc)) |new_loc| {
208 return new_loc.getSymbol(wasm_bin);207 return new_loc.getSymbol(wasm_bin);
209 }208 }
210 if (self.file) |object_index| {209 if (loc.file) |object_index| {
211 const object = wasm_bin.objects.items[object_index];210 const object = wasm_bin.objects.items[object_index];
212 return &object.symtable[self.index];211 return &object.symtable[loc.index];
213 }212 }
214 return &wasm_bin.symbols.items[self.index];213 return &wasm_bin.symbols.items[loc.index];
215 }214 }
216215
217 /// From a given location, returns the name of the symbol.216 /// From a given location, returns the name of the symbol.
218 pub fn getName(self: SymbolLoc, wasm_bin: *const Wasm) []const u8 {217 pub fn getName(loc: SymbolLoc, wasm_bin: *const Wasm) []const u8 {
219 if (wasm_bin.discarded.get(self)) |new_loc| {218 if (wasm_bin.discarded.get(loc)) |new_loc| {
220 return new_loc.getName(wasm_bin);219 return new_loc.getName(wasm_bin);
221 }220 }
222 if (self.file) |object_index| {221 if (loc.file) |object_index| {
223 const object = wasm_bin.objects.items[object_index];222 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);
225 }224 }
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);
227 }226 }
228227
229 /// From a given symbol location, returns the final location.228 /// From a given symbol location, returns the final location.
230 /// e.g. when a symbol was resolved and replaced by the symbol229 /// e.g. when a symbol was resolved and replaced by the symbol
231 /// in a different file, this will return said location.230 /// in a different file, this will return said location.
232 /// If the symbol wasn't replaced by another, this will return231 /// If the symbol wasn't replaced by another, this will return
233 /// the given location itself.232 /// the given location itwasm.
234 pub fn finalLoc(self: SymbolLoc, wasm_bin: *const Wasm) SymbolLoc {233 pub fn finalLoc(loc: SymbolLoc, wasm_bin: *const Wasm) SymbolLoc {
235 if (wasm_bin.discarded.get(self)) |new_loc| {234 if (wasm_bin.discarded.get(loc)) |new_loc| {
236 return new_loc.finalLoc(wasm_bin);235 return new_loc.finalLoc(wasm_bin);
237 }236 }
238 return self;237 return loc;
239 }238 }
240};239};
241240
...@@ -258,12 +257,12 @@ pub const StringTable = struct {...@@ -258,12 +257,12 @@ pub const StringTable = struct {
258 /// When found, de-duplicates the string and returns the existing offset instead.257 /// When found, de-duplicates the string and returns the existing offset instead.
259 /// When the string is not found in the `string_table`, a new entry will be inserted258 /// When the string is not found in the `string_table`, a new entry will be inserted
260 /// and the new offset to its data will be returned.259 /// and the new offset to its data will be returned.
261 pub fn put(self: *StringTable, allocator: Allocator, string: []const u8) !u32 {260 pub fn put(table: *StringTable, allocator: Allocator, string: []const u8) !u32 {
262 const gop = try self.string_table.getOrPutContextAdapted(261 const gop = try table.string_table.getOrPutContextAdapted(
263 allocator,262 allocator,
264 string,263 string,
265 std.hash_map.StringIndexAdapter{ .bytes = &self.string_data },264 std.hash_map.StringIndexAdapter{ .bytes = &table.string_data },
266 .{ .bytes = &self.string_data },265 .{ .bytes = &table.string_data },
267 );266 );
268 if (gop.found_existing) {267 if (gop.found_existing) {
269 const off = gop.key_ptr.*;268 const off = gop.key_ptr.*;
...@@ -271,13 +270,13 @@ pub const StringTable = struct {...@@ -271,13 +270,13 @@ pub const StringTable = struct {
271 return off;270 return off;
272 }271 }
273272
274 try self.string_data.ensureUnusedCapacity(allocator, string.len + 1);273 try table.string_data.ensureUnusedCapacity(allocator, string.len + 1);
275 const offset = @intCast(u32, self.string_data.items.len);274 const offset = @intCast(u32, table.string_data.items.len);
276275
277 log.debug("writing new string '{s}' at offset 0x{x}", .{ string, offset });276 log.debug("writing new string '{s}' at offset 0x{x}", .{ string, offset });
278277
279 self.string_data.appendSliceAssumeCapacity(string);278 table.string_data.appendSliceAssumeCapacity(string);
280 self.string_data.appendAssumeCapacity(0);279 table.string_data.appendAssumeCapacity(0);
281280
282 gop.key_ptr.* = offset;281 gop.key_ptr.* = offset;
283282
...@@ -286,26 +285,26 @@ pub const StringTable = struct {...@@ -286,26 +285,26 @@ pub const StringTable = struct {
286285
287 /// From a given offset, returns its corresponding string value.286 /// From a given offset, returns its corresponding string value.
288 /// Asserts offset does not exceed bounds.287 /// Asserts offset does not exceed bounds.
289 pub fn get(self: StringTable, off: u32) []const u8 {288 pub fn get(table: StringTable, off: u32) []const u8 {
290 assert(off < self.string_data.items.len);289 assert(off < table.string_data.items.len);
291 return mem.sliceTo(@ptrCast([*:0]const u8, self.string_data.items.ptr + off), 0);290 return mem.sliceTo(@ptrCast([*:0]const u8, table.string_data.items.ptr + off), 0);
292 }291 }
293292
294 /// Returns the offset of a given string when it exists.293 /// Returns the offset of a given string when it exists.
295 /// Will return null if the given string does not yet exist within the string table.294 /// 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 {295 pub fn getOffset(table: *StringTable, string: []const u8) ?u32 {
297 return self.string_table.getKeyAdapted(296 return table.string_table.getKeyAdapted(
298 string,297 string,
299 std.hash_map.StringIndexAdapter{ .bytes = &self.string_data },298 std.hash_map.StringIndexAdapter{ .bytes = &table.string_data },
300 );299 );
301 }300 }
302301
303 /// Frees all resources of the string table. Any references pointing302 /// Frees all resources of the string table. Any references pointing
304 /// to the strings will be invalid.303 /// to the strings will be invalid.
305 pub fn deinit(self: *StringTable, allocator: Allocator) void {304 pub fn deinit(table: *StringTable, allocator: Allocator) void {
306 self.string_data.deinit(allocator);305 table.string_data.deinit(allocator);
307 self.string_table.deinit(allocator);306 table.string_table.deinit(allocator);
308 self.* = undefined;307 table.* = undefined;
309 }308 }
310};309};
311310
...@@ -370,9 +369,9 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -370,9 +369,9 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
370}369}
371370
372pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {371pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
373 const self = try gpa.create(Wasm);372 const wasm = try gpa.create(Wasm);
374 errdefer gpa.destroy(self);373 errdefer gpa.destroy(wasm);
375 self.* = .{374 wasm.* = .{
376 .base = .{375 .base = .{
377 .tag = .wasm,376 .tag = .wasm,
378 .options = options,377 .options = options,
...@@ -385,33 +384,33 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {...@@ -385,33 +384,33 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
385 const use_llvm = build_options.have_llvm and options.use_llvm;384 const use_llvm = build_options.have_llvm and options.use_llvm;
386 const use_stage1 = build_options.have_stage1 and options.use_stage1;385 const use_stage1 = build_options.have_stage1 and options.use_stage1;
387 if (use_llvm and !use_stage1) {386 if (use_llvm and !use_stage1) {
388 self.llvm_object = try LlvmObject.create(gpa, options);387 wasm.llvm_object = try LlvmObject.create(gpa, options);
389 }388 }
390 return self;389 return wasm;
391}390}
392391
393/// Initializes symbols and atoms for the debug sections392/// Initializes symbols and atoms for the debug sections
394/// Initialization is only done when compiling Zig code.393/// Initialization is only done when compiling Zig code.
395/// When Zig is invoked as a linker instead, the atoms394/// When Zig is invoked as a linker instead, the atoms
396/// and symbols come from the object files instead.395/// and symbols come from the object files instead.
397pub fn initDebugSections(self: *Wasm) !void {396pub fn initDebugSections(wasm: *Wasm) !void {
398 if (self.dwarf == null) return; // not compiling Zig code, so no need to pre-initialize debug sections397 if (wasm.dwarf == null) return; // not compiling Zig code, so no need to pre-initialize debug sections
399 assert(self.debug_info_index == null);398 assert(wasm.debug_info_index == null);
400 // this will create an Atom and set the index for us.399 // 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");400 wasm.debug_info_atom = try wasm.createDebugSectionForIndex(&wasm.debug_info_index, ".debug_info");
402 self.debug_line_atom = try self.createDebugSectionForIndex(&self.debug_line_index, ".debug_line");401 wasm.debug_line_atom = try wasm.createDebugSectionForIndex(&wasm.debug_line_index, ".debug_line");
403 self.debug_loc_atom = try self.createDebugSectionForIndex(&self.debug_loc_index, ".debug_loc");402 wasm.debug_loc_atom = try wasm.createDebugSectionForIndex(&wasm.debug_loc_index, ".debug_loc");
404 self.debug_abbrev_atom = try self.createDebugSectionForIndex(&self.debug_abbrev_index, ".debug_abbrev");403 wasm.debug_abbrev_atom = try wasm.createDebugSectionForIndex(&wasm.debug_abbrev_index, ".debug_abbrev");
405 self.debug_ranges_atom = try self.createDebugSectionForIndex(&self.debug_ranges_index, ".debug_ranges");404 wasm.debug_ranges_atom = try wasm.createDebugSectionForIndex(&wasm.debug_ranges_index, ".debug_ranges");
406 self.debug_str_atom = try self.createDebugSectionForIndex(&self.debug_str_index, ".debug_str");405 wasm.debug_str_atom = try wasm.createDebugSectionForIndex(&wasm.debug_str_index, ".debug_str");
407 self.debug_pubnames_atom = try self.createDebugSectionForIndex(&self.debug_pubnames_index, ".debug_pubnames");406 wasm.debug_pubnames_atom = try wasm.createDebugSectionForIndex(&wasm.debug_pubnames_index, ".debug_pubnames");
408 self.debug_pubtypes_atom = try self.createDebugSectionForIndex(&self.debug_pubtypes_index, ".debug_pubtypes");407 wasm.debug_pubtypes_atom = try wasm.createDebugSectionForIndex(&wasm.debug_pubtypes_index, ".debug_pubtypes");
409}408}
410409
411fn parseInputFiles(self: *Wasm, files: []const []const u8) !void {410fn parseInputFiles(wasm: *Wasm, files: []const []const u8) !void {
412 for (files) |path| {411 for (files) |path| {
413 if (try self.parseObjectFile(path)) continue;412 if (try wasm.parseObjectFile(path)) continue;
414 if (try self.parseArchive(path, false)) continue; // load archives lazily413 if (try wasm.parseArchive(path, false)) continue; // load archives lazily
415 log.warn("Unexpected file format at path: '{s}'", .{path});414 log.warn("Unexpected file format at path: '{s}'", .{path});
416 }415 }
417}416}
...@@ -419,16 +418,16 @@ fn parseInputFiles(self: *Wasm, files: []const []const u8) !void {...@@ -419,16 +418,16 @@ fn parseInputFiles(self: *Wasm, files: []const []const u8) !void {
419/// Parses the object file from given path. Returns true when the given file was an object418/// Parses the object file from given path. Returns true when the given file was an object
420/// file and parsed successfully. Returns false when file is not an object file.419/// file and parsed successfully. Returns false when file is not an object file.
421/// May return an error instead when parsing failed.420/// May return an error instead when parsing failed.
422fn parseObjectFile(self: *Wasm, path: []const u8) !bool {421fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {
423 const file = try fs.cwd().openFile(path, .{});422 const file = try fs.cwd().openFile(path, .{});
424 errdefer file.close();423 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) {
427 error.InvalidMagicByte, error.NotObjectFile => return false,426 error.InvalidMagicByte, error.NotObjectFile => return false,
428 else => |e| return e,427 else => |e| return e,
429 };428 };
430 errdefer object.deinit(self.base.allocator);429 errdefer object.deinit(wasm.base.allocator);
431 try self.objects.append(self.base.allocator, object);430 try wasm.objects.append(wasm.base.allocator, object);
432 return true;431 return true;
433}432}
434433
...@@ -440,7 +439,7 @@ fn parseObjectFile(self: *Wasm, path: []const u8) !bool {...@@ -440,7 +439,7 @@ fn parseObjectFile(self: *Wasm, path: []const u8) !bool {
440/// When `force_load` is `true`, it will for link all object files in the archive.439/// When `force_load` is `true`, it will for link all object files in the archive.
441/// When false, it will only link with object files that contain symbols that440/// When false, it will only link with object files that contain symbols that
442/// are referenced by other object files or Zig code.441/// 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 {
444 const file = try fs.cwd().openFile(path, .{});443 const file = try fs.cwd().openFile(path, .{});
445 errdefer file.close();444 errdefer file.close();
446445
...@@ -448,25 +447,25 @@ fn parseArchive(self: *Wasm, path: []const u8, force_load: bool) !bool {...@@ -448,25 +447,25 @@ fn parseArchive(self: *Wasm, path: []const u8, force_load: bool) !bool {
448 .file = file,447 .file = file,
449 .name = path,448 .name = path,
450 };449 };
451 archive.parse(self.base.allocator) catch |err| switch (err) {450 archive.parse(wasm.base.allocator) catch |err| switch (err) {
452 error.EndOfStream, error.NotArchive => {451 error.EndOfStream, error.NotArchive => {
453 archive.deinit(self.base.allocator);452 archive.deinit(wasm.base.allocator);
454 return false;453 return false;
455 },454 },
456 else => |e| return e,455 else => |e| return e,
457 };456 };
458457
459 if (!force_load) {458 if (!force_load) {
460 errdefer archive.deinit(self.base.allocator);459 errdefer archive.deinit(wasm.base.allocator);
461 try self.archives.append(self.base.allocator, archive);460 try wasm.archives.append(wasm.base.allocator, archive);
462 return true;461 return true;
463 }462 }
464 defer archive.deinit(self.base.allocator);463 defer archive.deinit(wasm.base.allocator);
465464
466 // In this case we must force link all embedded object files within the archive465 // In this case we must force link all embedded object files within the archive
467 // We loop over all symbols, and then group them by offset as the offset466 // We loop over all symbols, and then group them by offset as the offset
468 // notates where the object file starts.467 // 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);
470 defer offsets.deinit();469 defer offsets.deinit();
471 for (archive.toc.values()) |symbol_offsets| {470 for (archive.toc.values()) |symbol_offsets| {
472 for (symbol_offsets.items) |sym_offset| {471 for (symbol_offsets.items) |sym_offset| {
...@@ -475,15 +474,15 @@ fn parseArchive(self: *Wasm, path: []const u8, force_load: bool) !bool {...@@ -475,15 +474,15 @@ fn parseArchive(self: *Wasm, path: []const u8, force_load: bool) !bool {
475 }474 }
476475
477 for (offsets.keys()) |file_offset| {476 for (offsets.keys()) |file_offset| {
478 const object = try self.objects.addOne(self.base.allocator);477 const object = try wasm.objects.addOne(wasm.base.allocator);
479 object.* = try archive.parseObject(self.base.allocator, file_offset);478 object.* = try archive.parseObject(wasm.base.allocator, file_offset);
480 }479 }
481480
482 return true;481 return true;
483}482}
484483
485fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {484fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
486 const object: Object = self.objects.items[object_index];485 const object: Object = wasm.objects.items[object_index];
487 log.debug("Resolving symbols in object: '{s}'", .{object.name});486 log.debug("Resolving symbols in object: '{s}'", .{object.name});
488487
489 for (object.symtable) |symbol, i| {488 for (object.symtable) |symbol, i| {
...@@ -496,7 +495,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {...@@ -496,7 +495,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
496 if (mem.eql(u8, sym_name, "__indirect_function_table")) {495 if (mem.eql(u8, sym_name, "__indirect_function_table")) {
497 continue;496 continue;
498 }497 }
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
501 if (symbol.isLocal()) {500 if (symbol.isLocal()) {
502 if (symbol.isUndefined()) {501 if (symbol.isUndefined()) {
...@@ -504,27 +503,27 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {...@@ -504,27 +503,27 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
504 log.err(" symbol '{s}' defined in '{s}'", .{ sym_name, object.name });503 log.err(" symbol '{s}' defined in '{s}'", .{ sym_name, object.name });
505 return error.undefinedLocal;504 return error.undefinedLocal;
506 }505 }
507 try self.resolved_symbols.putNoClobber(self.base.allocator, location, {});506 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {});
508 continue;507 continue;
509 }508 }
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);
512 if (!maybe_existing.found_existing) {511 if (!maybe_existing.found_existing) {
513 maybe_existing.value_ptr.* = location;512 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
516 if (symbol.isUndefined()) {515 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);
518 }517 }
519 continue;518 continue;
520 }519 }
521520
522 const existing_loc = maybe_existing.value_ptr.*;521 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
525 const existing_file_path = if (existing_loc.file) |file| blk: {524 const existing_file_path = if (existing_loc.file) |file| blk: {
526 break :blk self.objects.items[file].name;525 break :blk wasm.objects.items[file].name;
527 } else self.name;526 } else wasm.name;
528527
529 if (!existing_sym.isUndefined()) outer: {528 if (!existing_sym.isUndefined()) outer: {
530 if (!symbol.isUndefined()) inner: {529 if (!symbol.isUndefined()) inner: {
...@@ -541,7 +540,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {...@@ -541,7 +540,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
541 return error.SymbolCollision;540 return error.SymbolCollision;
542 }541 }
543542
544 try self.discarded.put(self.base.allocator, location, existing_loc);543 try wasm.discarded.put(wasm.base.allocator, location, existing_loc);
545 continue; // Do not overwrite defined symbols with undefined symbols544 continue; // Do not overwrite defined symbols with undefined symbols
546 }545 }
547546
...@@ -554,12 +553,12 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {...@@ -554,12 +553,12 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
554553
555 if (existing_sym.isUndefined() and symbol.isUndefined()) {554 if (existing_sym.isUndefined() and symbol.isUndefined()) {
556 const existing_name = if (existing_loc.file) |file_index| blk: {555 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];
558 const name_index = obj.findImport(symbol.tag.externalType(), existing_sym.index).module_name;557 const name_index = obj.findImport(symbol.tag.externalType(), existing_sym.index).module_name;
559 break :blk obj.string_table.get(name_index);558 break :blk obj.string_table.get(name_index);
560 } else blk: {559 } else blk: {
561 const name_index = self.imports.get(existing_loc).?.module_name;560 const name_index = wasm.imports.get(existing_loc).?.module_name;
562 break :blk self.string_table.get(name_index);561 break :blk wasm.string_table.get(name_index);
563 };562 };
564563
565 const module_index = object.findImport(symbol.tag.externalType(), symbol.index).module_name;564 const module_index = object.findImport(symbol.tag.externalType(), symbol.index).module_name;
...@@ -577,8 +576,8 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {...@@ -577,8 +576,8 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
577 }576 }
578577
579 if (existing_sym.tag == .global) {578 if (existing_sym.tag == .global) {
580 const existing_ty = self.getGlobalType(existing_loc);579 const existing_ty = wasm.getGlobalType(existing_loc);
581 const new_ty = self.getGlobalType(location);580 const new_ty = wasm.getGlobalType(location);
582 if (existing_ty.mutable != new_ty.mutable or existing_ty.valtype != new_ty.valtype) {581 if (existing_ty.mutable != new_ty.mutable or existing_ty.valtype != new_ty.valtype) {
583 log.err("symbol '{s}' mismatching global types", .{sym_name});582 log.err("symbol '{s}' mismatching global types", .{sym_name});
584 log.err(" first definition in '{s}'", .{existing_file_path});583 log.err(" first definition in '{s}'", .{existing_file_path});
...@@ -588,8 +587,8 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {...@@ -588,8 +587,8 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
588 }587 }
589588
590 if (existing_sym.tag == .function) {589 if (existing_sym.tag == .function) {
591 const existing_ty = self.getFunctionSignature(existing_loc);590 const existing_ty = wasm.getFunctionSignature(existing_loc);
592 const new_ty = self.getFunctionSignature(location);591 const new_ty = wasm.getFunctionSignature(location);
593 if (!existing_ty.eql(new_ty)) {592 if (!existing_ty.eql(new_ty)) {
594 log.err("symbol '{s}' mismatching function signatures.", .{sym_name});593 log.err("symbol '{s}' mismatching function signatures.", .{sym_name});
595 log.err(" expected signature {}, but found signature {}", .{ existing_ty, new_ty });594 log.err(" expected signature {}, but found signature {}", .{ existing_ty, new_ty });
...@@ -601,7 +600,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {...@@ -601,7 +600,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
601600
602 // when both symbols are weak, we skip overwriting601 // when both symbols are weak, we skip overwriting
603 if (existing_sym.isWeak() and symbol.isWeak()) {602 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);
605 continue;604 continue;
606 }605 }
607606
...@@ -609,27 +608,27 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {...@@ -609,27 +608,27 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
609 log.debug("Overwriting symbol '{s}'", .{sym_name});608 log.debug("Overwriting symbol '{s}'", .{sym_name});
610 log.debug(" old definition in '{s}'", .{existing_file_path});609 log.debug(" old definition in '{s}'", .{existing_file_path});
611 log.debug(" new definition in '{s}'", .{object.name});610 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);
613 maybe_existing.value_ptr.* = location;612 maybe_existing.value_ptr.* = location;
614 try self.globals.put(self.base.allocator, sym_name_index, location);613 try wasm.globals.put(wasm.base.allocator, sym_name_index, location);
615 try self.resolved_symbols.put(self.base.allocator, location, {});614 try wasm.resolved_symbols.put(wasm.base.allocator, location, {});
616 assert(self.resolved_symbols.swapRemove(existing_loc));615 assert(wasm.resolved_symbols.swapRemove(existing_loc));
617 if (existing_sym.isUndefined()) {616 if (existing_sym.isUndefined()) {
618 assert(self.undefs.swapRemove(sym_name));617 assert(wasm.undefs.swapRemove(sym_name));
619 }618 }
620 }619 }
621}620}
622621
623fn resolveSymbolsInArchives(self: *Wasm) !void {622fn resolveSymbolsInArchives(wasm: *Wasm) !void {
624 if (self.archives.items.len == 0) return;623 if (wasm.archives.items.len == 0) return;
625624
626 log.debug("Resolving symbols in archives", .{});625 log.debug("Resolving symbols in archives", .{});
627 var index: u32 = 0;626 var index: u32 = 0;
628 undef_loop: while (index < self.undefs.count()) {627 undef_loop: while (index < wasm.undefs.count()) {
629 const undef_sym_loc = self.undefs.values()[index];628 const undef_sym_loc = wasm.undefs.values()[index];
630 const sym_name = undef_sym_loc.getName(self);629 const sym_name = undef_sym_loc.getName(wasm);
631630
632 for (self.archives.items) |archive| {631 for (wasm.archives.items) |archive| {
633 const offset = archive.toc.get(sym_name) orelse {632 const offset = archive.toc.get(sym_name) orelse {
634 // symbol does not exist in this archive633 // symbol does not exist in this archive
635 continue;634 continue;
...@@ -639,10 +638,10 @@ fn resolveSymbolsInArchives(self: *Wasm) !void {...@@ -639,10 +638,10 @@ fn resolveSymbolsInArchives(self: *Wasm) !void {
639 // Symbol is found in unparsed object file within current archive.638 // Symbol is found in unparsed object file within current archive.
640 // Parse object and and resolve symbols again before we check remaining639 // Parse object and and resolve symbols again before we check remaining
641 // undefined symbols.640 // undefined symbols.
642 const object_file_index = @intCast(u16, self.objects.items.len);641 const object_file_index = @intCast(u16, wasm.objects.items.len);
643 var object = try archive.parseObject(self.base.allocator, offset.items[0]);642 var object = try archive.parseObject(wasm.base.allocator, offset.items[0]);
644 try self.objects.append(self.base.allocator, object);643 try wasm.objects.append(wasm.base.allocator, object);
645 try self.resolveSymbolsInObject(object_file_index);644 try wasm.resolveSymbolsInObject(object_file_index);
646645
647 // continue loop for any remaining undefined symbols that still exist646 // continue loop for any remaining undefined symbols that still exist
648 // after resolving last object file647 // after resolving last object file
...@@ -652,18 +651,18 @@ fn resolveSymbolsInArchives(self: *Wasm) !void {...@@ -652,18 +651,18 @@ fn resolveSymbolsInArchives(self: *Wasm) !void {
652 }651 }
653}652}
654653
655fn checkUndefinedSymbols(self: *const Wasm) !void {654fn checkUndefinedSymbols(wasm: *const Wasm) !void {
656 if (self.base.options.output_mode == .Obj) return;655 if (wasm.base.options.output_mode == .Obj) return;
657656
658 var found_undefined_symbols = false;657 var found_undefined_symbols = false;
659 for (self.undefs.values()) |undef| {658 for (wasm.undefs.values()) |undef| {
660 const symbol = undef.getSymbol(self);659 const symbol = undef.getSymbol(wasm);
661 if (symbol.tag == .data) {660 if (symbol.tag == .data) {
662 found_undefined_symbols = true;661 found_undefined_symbols = true;
663 const file_name = if (undef.file) |file_index| name: {662 const file_name = if (undef.file) |file_index| name: {
664 break :name self.objects.items[file_index].name;663 break :name wasm.objects.items[file_index].name;
665 } else self.name;664 } else wasm.name;
666 log.err("could not resolve undefined symbol '{s}'", .{undef.getName(self)});665 log.err("could not resolve undefined symbol '{s}'", .{undef.getName(wasm)});
667 log.err(" defined in '{s}'", .{file_name});666 log.err(" defined in '{s}'", .{file_name});
668 }667 }
669 }668 }
...@@ -672,80 +671,80 @@ fn checkUndefinedSymbols(self: *const Wasm) !void {...@@ -672,80 +671,80 @@ fn checkUndefinedSymbols(self: *const Wasm) !void {
672 }671 }
673}672}
674673
675pub fn deinit(self: *Wasm) void {674pub fn deinit(wasm: *Wasm) void {
676 const gpa = self.base.allocator;675 const gpa = wasm.base.allocator;
677 if (build_options.have_llvm) {676 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);
679 }678 }
680679
681 if (self.base.options.module) |mod| {680 if (wasm.base.options.module) |mod| {
682 var decl_it = self.decls.keyIterator();681 var decl_it = wasm.decls.keyIterator();
683 while (decl_it.next()) |decl_index_ptr| {682 while (decl_it.next()) |decl_index_ptr| {
684 const decl = mod.declPtr(decl_index_ptr.*);683 const decl = mod.declPtr(decl_index_ptr.*);
685 decl.link.wasm.deinit(gpa);684 decl.link.wasm.deinit(gpa);
686 }685 }
687 } else {686 } else {
688 assert(self.decls.count() == 0);687 assert(wasm.decls.count() == 0);
689 }688 }
690689
691 for (self.func_types.items) |*func_type| {690 for (wasm.func_types.items) |*func_type| {
692 func_type.deinit(gpa);691 func_type.deinit(gpa);
693 }692 }
694 for (self.segment_info.values()) |segment_info| {693 for (wasm.segment_info.values()) |segment_info| {
695 gpa.free(segment_info.name);694 gpa.free(segment_info.name);
696 }695 }
697 for (self.objects.items) |*object| {696 for (wasm.objects.items) |*object| {
698 object.deinit(gpa);697 object.deinit(gpa);
699 }698 }
700699
701 for (self.archives.items) |*archive| {700 for (wasm.archives.items) |*archive| {
702 archive.deinit(gpa);701 archive.deinit(gpa);
703 }702 }
704703
705 self.decls.deinit(gpa);704 wasm.decls.deinit(gpa);
706 self.symbols.deinit(gpa);705 wasm.symbols.deinit(gpa);
707 self.symbols_free_list.deinit(gpa);706 wasm.symbols_free_list.deinit(gpa);
708 self.globals.deinit(gpa);707 wasm.globals.deinit(gpa);
709 self.resolved_symbols.deinit(gpa);708 wasm.resolved_symbols.deinit(gpa);
710 self.undefs.deinit(gpa);709 wasm.undefs.deinit(gpa);
711 self.discarded.deinit(gpa);710 wasm.discarded.deinit(gpa);
712 self.symbol_atom.deinit(gpa);711 wasm.symbol_atom.deinit(gpa);
713 self.export_names.deinit(gpa);712 wasm.export_names.deinit(gpa);
714 self.atoms.deinit(gpa);713 wasm.atoms.deinit(gpa);
715 for (self.managed_atoms.items) |managed_atom| {714 for (wasm.managed_atoms.items) |managed_atom| {
716 managed_atom.deinit(gpa);715 managed_atom.deinit(gpa);
717 gpa.destroy(managed_atom);716 gpa.destroy(managed_atom);
718 }717 }
719 self.managed_atoms.deinit(gpa);718 wasm.managed_atoms.deinit(gpa);
720 self.segments.deinit(gpa);719 wasm.segments.deinit(gpa);
721 self.data_segments.deinit(gpa);720 wasm.data_segments.deinit(gpa);
722 self.segment_info.deinit(gpa);721 wasm.segment_info.deinit(gpa);
723 self.objects.deinit(gpa);722 wasm.objects.deinit(gpa);
724 self.archives.deinit(gpa);723 wasm.archives.deinit(gpa);
725724
726 // free output sections725 // free output sections
727 self.imports.deinit(gpa);726 wasm.imports.deinit(gpa);
728 self.func_types.deinit(gpa);727 wasm.func_types.deinit(gpa);
729 self.functions.deinit(gpa);728 wasm.functions.deinit(gpa);
730 self.wasm_globals.deinit(gpa);729 wasm.wasm_globals.deinit(gpa);
731 self.function_table.deinit(gpa);730 wasm.function_table.deinit(gpa);
732 self.tables.deinit(gpa);731 wasm.tables.deinit(gpa);
733 self.exports.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| {
738 dwarf.deinit();737 dwarf.deinit();
739 }738 }
740}739}
741740
742pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {741pub fn allocateDeclIndexes(wasm: *Wasm, decl_index: Module.Decl.Index) !void {
743 if (self.llvm_object) |_| return;742 if (wasm.llvm_object) |_| return;
744 const decl = self.base.options.module.?.declPtr(decl_index);743 const decl = wasm.base.options.module.?.declPtr(decl_index);
745 if (decl.link.wasm.sym_index != 0) return;744 if (decl.link.wasm.sym_index != 0) return;
746745
747 try self.symbols.ensureUnusedCapacity(self.base.allocator, 1);746 try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1);
748 try self.decls.putNoClobber(self.base.allocator, decl_index, {});747 try wasm.decls.putNoClobber(wasm.base.allocator, decl_index, {});
749748
750 const atom = &decl.link.wasm;749 const atom = &decl.link.wasm;
751750
...@@ -756,22 +755,22 @@ pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {...@@ -756,22 +755,22 @@ pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {
756 .index = undefined, // will be set after updateDecl755 .index = undefined, // will be set after updateDecl
757 };756 };
758757
759 if (self.symbols_free_list.popOrNull()) |index| {758 if (wasm.symbols_free_list.popOrNull()) |index| {
760 atom.sym_index = index;759 atom.sym_index = index;
761 self.symbols.items[index] = symbol;760 wasm.symbols.items[index] = symbol;
762 } else {761 } else {
763 atom.sym_index = @intCast(u32, self.symbols.items.len);762 atom.sym_index = @intCast(u32, wasm.symbols.items.len);
764 self.symbols.appendAssumeCapacity(symbol);763 wasm.symbols.appendAssumeCapacity(symbol);
765 }764 }
766 try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);765 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, atom.symbolLoc(), atom);
767}766}
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 {
770 if (build_options.skip_non_native and builtin.object_format != .wasm) {769 if (build_options.skip_non_native and builtin.object_format != .wasm) {
771 @panic("Attempted to compile for object format that was disabled by build configuration");770 @panic("Attempted to compile for object format that was disabled by build configuration");
772 }771 }
773 if (build_options.have_llvm) {772 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);
775 }774 }
776775
777 const tracy = trace(@src());776 const tracy = trace(@src());
...@@ -783,13 +782,13 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes...@@ -783,13 +782,13 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
783782
784 decl.link.wasm.clear();783 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;
787 defer if (decl_state) |*ds| ds.deinit();786 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);
790 defer code_writer.deinit();789 defer code_writer.deinit();
791 const result = try codegen.generateFunction(790 const result = try codegen.generateFunction(
792 &self.base,791 &wasm.base,
793 decl.srcLoc(),792 decl.srcLoc(),
794 func,793 func,
795 air,794 air,
...@@ -807,9 +806,9 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes...@@ -807,9 +806,9 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
807 },806 },
808 };807 };
809808
810 if (self.dwarf) |*dwarf| {809 if (wasm.dwarf) |*dwarf| {
811 try dwarf.commitDeclState(810 try dwarf.commitDeclState(
812 &self.base,811 &wasm.base,
813 mod,812 mod,
814 decl,813 decl,
815 // Actual value will be written after relocation.814 // Actual value will be written after relocation.
...@@ -820,17 +819,17 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes...@@ -820,17 +819,17 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
820 &decl_state.?,819 &decl_state.?,
821 );820 );
822 }821 }
823 return self.finishUpdateDecl(decl, code);822 return wasm.finishUpdateDecl(decl, code);
824}823}
825824
826// Generate code for the Decl, storing it in memory to be later written to825// Generate code for the Decl, storing it in memory to be later written to
827// the file on flush().826// 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 {
829 if (build_options.skip_non_native and builtin.object_format != .wasm) {828 if (build_options.skip_non_native and builtin.object_format != .wasm) {
830 @panic("Attempted to compile for object format that was disabled by build configuration");829 @panic("Attempted to compile for object format that was disabled by build configuration");
831 }830 }
832 if (build_options.have_llvm) {831 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);
834 }833 }
835834
836 const tracy = trace(@src());835 const tracy = trace(@src());
...@@ -850,15 +849,15 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -850,15 +849,15 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
850 if (decl.isExtern()) {849 if (decl.isExtern()) {
851 const variable = decl.getVariable().?;850 const variable = decl.getVariable().?;
852 const name = mem.sliceTo(decl.name, 0);851 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);
854 }853 }
855 const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;854 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);
858 defer code_writer.deinit();857 defer code_writer.deinit();
859858
860 const res = try codegen.generateSymbol(859 const res = try codegen.generateSymbol(
861 &self.base,860 &wasm.base,
862 decl.srcLoc(),861 decl.srcLoc(),
863 .{ .ty = decl.ty, .val = val },862 .{ .ty = decl.ty, .val = val },
864 &code_writer,863 &code_writer,
...@@ -876,46 +875,46 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -876,46 +875,46 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
876 },875 },
877 };876 };
878877
879 return self.finishUpdateDecl(decl, code);878 return wasm.finishUpdateDecl(decl, code);
880}879}
881880
882pub fn updateDeclLineNumber(self: *Wasm, mod: *Module, decl: *const Module.Decl) !void {881pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl: *const Module.Decl) !void {
883 if (self.llvm_object) |_| return;882 if (wasm.llvm_object) |_| return;
884 if (self.dwarf) |*dw| {883 if (wasm.dwarf) |*dw| {
885 const tracy = trace(@src());884 const tracy = trace(@src());
886 defer tracy.end();885 defer tracy.end();
887886
888 const decl_name = try decl.getFullyQualifiedName(mod);887 const decl_name = try decl.getFullyQualifiedName(mod);
889 defer self.base.allocator.free(decl_name);888 defer wasm.base.allocator.free(decl_name);
890889
891 log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });890 log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
892 try dw.updateDeclLineNumber(&self.base, decl);891 try dw.updateDeclLineNumber(&wasm.base, decl);
893 }892 }
894}893}
895894
896fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {895fn finishUpdateDecl(wasm: *Wasm, decl: *Module.Decl, code: []const u8) !void {
897 const mod = self.base.options.module.?;896 const mod = wasm.base.options.module.?;
898 const atom: *Atom = &decl.link.wasm;897 const atom: *Atom = &decl.link.wasm;
899 const symbol = &self.symbols.items[atom.sym_index];898 const symbol = &wasm.symbols.items[atom.sym_index];
900 const full_name = try decl.getFullyQualifiedName(mod);899 const full_name = try decl.getFullyQualifiedName(mod);
901 defer self.base.allocator.free(full_name);900 defer wasm.base.allocator.free(full_name);
902 symbol.name = try self.string_table.put(self.base.allocator, full_name);901 symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);
903 try atom.code.appendSlice(self.base.allocator, code);902 try atom.code.appendSlice(wasm.base.allocator, code);
904 try self.resolved_symbols.put(self.base.allocator, atom.symbolLoc(), {});903 try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {});
905904
906 if (code.len == 0) return;905 if (code.len == 0) return;
907 atom.size = @intCast(u32, code.len);906 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);
909}908}
910909
911/// From a given symbol location, returns its `wasm.GlobalType`.910/// From a given symbol location, returns its `wasm.GlobalType`.
912/// Asserts the Symbol represents a global.911/// Asserts the Symbol represents a global.
913fn getGlobalType(self: *const Wasm, loc: SymbolLoc) wasm.GlobalType {912fn getGlobalType(wasm: *const Wasm, loc: SymbolLoc) std.wasm.GlobalType {
914 const symbol = loc.getSymbol(self);913 const symbol = loc.getSymbol(wasm);
915 assert(symbol.tag == .global);914 assert(symbol.tag == .global);
916 const is_undefined = symbol.isUndefined();915 const is_undefined = symbol.isUndefined();
917 if (loc.file) |file_index| {916 if (loc.file) |file_index| {
918 const obj: Object = self.objects.items[file_index];917 const obj: Object = wasm.objects.items[file_index];
919 if (is_undefined) {918 if (is_undefined) {
920 return obj.findImport(.global, symbol.index).kind.global;919 return obj.findImport(.global, symbol.index).kind.global;
921 }920 }
...@@ -923,19 +922,19 @@ fn getGlobalType(self: *const Wasm, loc: SymbolLoc) wasm.GlobalType {...@@ -923,19 +922,19 @@ fn getGlobalType(self: *const Wasm, loc: SymbolLoc) wasm.GlobalType {
923 return obj.globals[symbol.index - import_global_count].global_type;922 return obj.globals[symbol.index - import_global_count].global_type;
924 }923 }
925 if (is_undefined) {924 if (is_undefined) {
926 return self.imports.get(loc).?.kind.global;925 return wasm.imports.get(loc).?.kind.global;
927 }926 }
928 return self.wasm_globals.items[symbol.index].global_type;927 return wasm.wasm_globals.items[symbol.index].global_type;
929}928}
930929
931/// From a given symbol location, returns its `wasm.Type`.930/// From a given symbol location, returns its `wasm.Type`.
932/// Asserts the Symbol represents a function.931/// Asserts the Symbol represents a function.
933fn getFunctionSignature(self: *const Wasm, loc: SymbolLoc) wasm.Type {932fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type {
934 const symbol = loc.getSymbol(self);933 const symbol = loc.getSymbol(wasm);
935 assert(symbol.tag == .function);934 assert(symbol.tag == .function);
936 const is_undefined = symbol.isUndefined();935 const is_undefined = symbol.isUndefined();
937 if (loc.file) |file_index| {936 if (loc.file) |file_index| {
938 const obj: Object = self.objects.items[file_index];937 const obj: Object = wasm.objects.items[file_index];
939 if (is_undefined) {938 if (is_undefined) {
940 const ty_index = obj.findImport(.function, symbol.index).kind.function;939 const ty_index = obj.findImport(.function, symbol.index).kind.function;
941 return obj.func_types[ty_index];940 return obj.func_types[ty_index];
...@@ -945,55 +944,55 @@ fn getFunctionSignature(self: *const Wasm, loc: SymbolLoc) wasm.Type {...@@ -945,55 +944,55 @@ fn getFunctionSignature(self: *const Wasm, loc: SymbolLoc) wasm.Type {
945 return obj.func_types[type_index];944 return obj.func_types[type_index];
946 }945 }
947 if (is_undefined) {946 if (is_undefined) {
948 const ty_index = self.imports.get(loc).?.kind.function;947 const ty_index = wasm.imports.get(loc).?.kind.function;
949 return self.func_types.items[ty_index];948 return wasm.func_types.items[ty_index];
950 }949 }
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];
952}951}
953952
954/// Lowers a constant typed value to a local symbol and atom.953/// Lowers a constant typed value to a local symbol and atom.
955/// Returns the symbol index of the local954/// Returns the symbol index of the local
956/// The given `decl` is the parent decl whom owns the constant.955/// 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 {
958 assert(tv.ty.zigTypeTag() != .Fn); // cannot create local symbols for functions957 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.?;
961 const decl = mod.declPtr(decl_index);960 const decl = mod.declPtr(decl_index);
962961
963 // Create and initialize a new local symbol and atom962 // Create and initialize a new local symbol and atom
964 const local_index = decl.link.wasm.locals.items.len;963 const local_index = decl.link.wasm.locals.items.len;
965 const fqdn = try decl.getFullyQualifiedName(mod);964 const fqdn = try decl.getFullyQualifiedName(mod);
966 defer self.base.allocator.free(fqdn);965 defer wasm.base.allocator.free(fqdn);
967 const name = try std.fmt.allocPrintZ(self.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index });966 const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index });
968 defer self.base.allocator.free(name);967 defer wasm.base.allocator.free(name);
969 var symbol: Symbol = .{968 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),
971 .flags = 0,970 .flags = 0,
972 .tag = .data,971 .tag = .data,
973 .index = undefined,972 .index = undefined,
974 };973 };
975 symbol.setFlag(.WASM_SYM_BINDING_LOCAL);974 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);
978 atom.* = Atom.empty;977 atom.* = Atom.empty;
979 atom.alignment = tv.ty.abiAlignment(self.base.options.target);978 atom.alignment = tv.ty.abiAlignment(wasm.base.options.target);
980 try self.symbols.ensureUnusedCapacity(self.base.allocator, 1);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| {
983 atom.sym_index = index;982 atom.sym_index = index;
984 self.symbols.items[index] = symbol;983 wasm.symbols.items[index] = symbol;
985 } else {984 } else {
986 atom.sym_index = @intCast(u32, self.symbols.items.len);985 atom.sym_index = @intCast(u32, wasm.symbols.items.len);
987 self.symbols.appendAssumeCapacity(symbol);986 wasm.symbols.appendAssumeCapacity(symbol);
988 }987 }
989 try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});988 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, atom.symbolLoc(), {});
990 try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);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);
993 defer value_bytes.deinit();992 defer value_bytes.deinit();
994993
995 const result = try codegen.generateSymbol(994 const result = try codegen.generateSymbol(
996 &self.base,995 &wasm.base,
997 decl.srcLoc(),996 decl.srcLoc(),
998 tv,997 tv,
999 &value_bytes,998 &value_bytes,
...@@ -1014,7 +1013,7 @@ pub fn lowerUnnamedConst(self: *Wasm, tv: TypedValue, decl_index: Module.Decl.In...@@ -1014,7 +1013,7 @@ pub fn lowerUnnamedConst(self: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
1014 };1013 };
10151014
1016 atom.size = @intCast(u32, code.len);1015 atom.size = @intCast(u32, code.len);
1017 try atom.code.appendSlice(self.base.allocator, code);1016 try atom.code.appendSlice(wasm.base.allocator, code);
1018 return atom.sym_index;1017 return atom.sym_index;
1019}1018}
10201019
...@@ -1022,9 +1021,9 @@ pub fn lowerUnnamedConst(self: *Wasm, tv: TypedValue, decl_index: Module.Decl.In...@@ -1022,9 +1021,9 @@ pub fn lowerUnnamedConst(self: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
1022/// such as an exported or imported symbol.1021/// such as an exported or imported symbol.
1023/// If the symbol does not yet exist, creates a new one symbol instead1022/// If the symbol does not yet exist, creates a new one symbol instead
1024/// and then returns the index to it.1023/// and then returns the index to it.
1025pub fn getGlobalSymbol(self: *Wasm, name: []const u8) !u32 {1024pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8) !u32 {
1026 const name_index = try self.string_table.put(self.base.allocator, name);1025 const name_index = try wasm.string_table.put(wasm.base.allocator, name);
1027 const gop = try self.globals.getOrPut(self.base.allocator, name_index);1026 const gop = try wasm.globals.getOrPut(wasm.base.allocator, name_index);
1028 if (gop.found_existing) {1027 if (gop.found_existing) {
1029 return gop.value_ptr.*.index;1028 return gop.value_ptr.*.index;
1030 }1029 }
...@@ -1038,46 +1037,46 @@ pub fn getGlobalSymbol(self: *Wasm, name: []const u8) !u32 {...@@ -1038,46 +1037,46 @@ pub fn getGlobalSymbol(self: *Wasm, name: []const u8) !u32 {
1038 symbol.setGlobal(true);1037 symbol.setGlobal(true);
1039 symbol.setUndefined(true);1038 symbol.setUndefined(true);
10401039
1041 const sym_index = if (self.symbols_free_list.popOrNull()) |index| index else blk: {1040 const sym_index = if (wasm.symbols_free_list.popOrNull()) |index| index else blk: {
1042 var index = @intCast(u32, self.symbols.items.len);1041 var index = @intCast(u32, wasm.symbols.items.len);
1043 try self.symbols.ensureUnusedCapacity(self.base.allocator, 1);1042 try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1);
1044 self.symbols.items.len += 1;1043 wasm.symbols.items.len += 1;
1045 break :blk index;1044 break :blk index;
1046 };1045 };
1047 self.symbols.items[sym_index] = symbol;1046 wasm.symbols.items[sym_index] = symbol;
1048 gop.value_ptr.* = .{ .index = sym_index, .file = null };1047 gop.value_ptr.* = .{ .index = sym_index, .file = null };
1049 try self.resolved_symbols.put(self.base.allocator, gop.value_ptr.*, {});1048 try wasm.resolved_symbols.put(wasm.base.allocator, gop.value_ptr.*, {});
1050 try self.undefs.putNoClobber(self.base.allocator, name, gop.value_ptr.*);1049 try wasm.undefs.putNoClobber(wasm.base.allocator, name, gop.value_ptr.*);
1051 return sym_index;1050 return sym_index;
1052}1051}
10531052
1054/// For a given decl, find the given symbol index's atom, and create a relocation for the type.1053/// For a given decl, find the given symbol index's atom, and create a relocation for the type.
1055/// Returns the given pointer address1054/// Returns the given pointer address
1056pub fn getDeclVAddr(1055pub fn getDeclVAddr(
1057 self: *Wasm,1056 wasm: *Wasm,
1058 decl_index: Module.Decl.Index,1057 decl_index: Module.Decl.Index,
1059 reloc_info: link.File.RelocInfo,1058 reloc_info: link.File.RelocInfo,
1060) !u64 {1059) !u64 {
1061 const mod = self.base.options.module.?;1060 const mod = wasm.base.options.module.?;
1062 const decl = mod.declPtr(decl_index);1061 const decl = mod.declPtr(decl_index);
1063 const target_symbol_index = decl.link.wasm.sym_index;1062 const target_symbol_index = decl.link.wasm.sym_index;
1064 assert(target_symbol_index != 0);1063 assert(target_symbol_index != 0);
1065 assert(reloc_info.parent_atom_index != 0);1064 assert(reloc_info.parent_atom_index != 0);
1066 const atom = self.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;1065 const atom = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;
1067 const is_wasm32 = self.base.options.target.cpu.arch == .wasm32;1066 const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32;
1068 if (decl.ty.zigTypeTag() == .Fn) {1067 if (decl.ty.zigTypeTag() == .Fn) {
1069 assert(reloc_info.addend == 0); // addend not allowed for function relocations1068 assert(reloc_info.addend == 0); // addend not allowed for function relocations
1070 // We found a function pointer, so add it to our table,1069 // We found a function pointer, so add it to our table,
1071 // as function pointers are not allowed to be stored inside the data section.1070 // as function pointers are not allowed to be stored inside the data section.
1072 // They are instead stored in a function table which are called by index.1071 // They are instead stored in a function table which are called by index.
1073 try self.addTableFunction(target_symbol_index);1072 try wasm.addTableFunction(target_symbol_index);
1074 try atom.relocs.append(self.base.allocator, .{1073 try atom.relocs.append(wasm.base.allocator, .{
1075 .index = target_symbol_index,1074 .index = target_symbol_index,
1076 .offset = @intCast(u32, reloc_info.offset),1075 .offset = @intCast(u32, reloc_info.offset),
1077 .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64,1076 .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64,
1078 });1077 });
1079 } else {1078 } else {
1080 try atom.relocs.append(self.base.allocator, .{1079 try atom.relocs.append(wasm.base.allocator, .{
1081 .index = target_symbol_index,1080 .index = target_symbol_index,
1082 .offset = @intCast(u32, reloc_info.offset),1081 .offset = @intCast(u32, reloc_info.offset),
1083 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64,1082 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64,
...@@ -1091,22 +1090,22 @@ pub fn getDeclVAddr(...@@ -1091,22 +1090,22 @@ pub fn getDeclVAddr(
1091 return target_symbol_index;1090 return target_symbol_index;
1092}1091}
10931092
1094pub fn deleteExport(self: *Wasm, exp: Export) void {1093pub fn deleteExport(wasm: *Wasm, exp: Export) void {
1095 if (self.llvm_object) |_| return;1094 if (wasm.llvm_object) |_| return;
1096 const sym_index = exp.sym_index orelse return;1095 const sym_index = exp.sym_index orelse return;
1097 const loc: SymbolLoc = .{ .file = null, .index = sym_index };1096 const loc: SymbolLoc = .{ .file = null, .index = sym_index };
1098 const symbol = loc.getSymbol(self);1097 const symbol = loc.getSymbol(wasm);
1099 const symbol_name = self.string_table.get(symbol.name);1098 const symbol_name = wasm.string_table.get(symbol.name);
1100 log.debug("Deleting export for decl '{s}'", .{symbol_name});1099 log.debug("Deleting export for decl '{s}'", .{symbol_name});
1101 if (self.export_names.fetchRemove(loc)) |kv| {1100 if (wasm.export_names.fetchRemove(loc)) |kv| {
1102 assert(self.globals.remove(kv.value));1101 assert(wasm.globals.remove(kv.value));
1103 } else {1102 } else {
1104 assert(self.globals.remove(symbol.name));1103 assert(wasm.globals.remove(symbol.name));
1105 }1104 }
1106}1105}
11071106
1108pub fn updateDeclExports(1107pub fn updateDeclExports(
1109 self: *Wasm,1108 wasm: *Wasm,
1110 mod: *Module,1109 mod: *Module,
1111 decl_index: Module.Decl.Index,1110 decl_index: Module.Decl.Index,
1112 exports: []const *Module.Export,1111 exports: []const *Module.Export,
...@@ -1115,7 +1114,7 @@ pub fn updateDeclExports(...@@ -1115,7 +1114,7 @@ pub fn updateDeclExports(
1115 @panic("Attempted to compile for object format that was disabled by build configuration");1114 @panic("Attempted to compile for object format that was disabled by build configuration");
1116 }1115 }
1117 if (build_options.have_llvm) {1116 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);
1119 }1118 }
11201119
1121 const decl = mod.declPtr(decl_index);1120 const decl = mod.declPtr(decl_index);
...@@ -1131,10 +1130,10 @@ pub fn updateDeclExports(...@@ -1131,10 +1130,10 @@ pub fn updateDeclExports(
1131 continue;1130 continue;
1132 }1131 }
11331132
1134 const export_name = try self.string_table.put(self.base.allocator, exp.options.name);1133 const export_name = try wasm.string_table.put(wasm.base.allocator, exp.options.name);
1135 if (self.globals.getPtr(export_name)) |existing_loc| {1134 if (wasm.globals.getPtr(export_name)) |existing_loc| {
1136 if (existing_loc.index == decl.link.wasm.sym_index) continue;1135 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
1139 const exp_is_weak = exp.options.linkage == .Internal or exp.options.linkage == .Weak;1138 const exp_is_weak = exp.options.linkage == .Internal or exp.options.linkage == .Weak;
1140 // When both the to-bo-exported symbol and the already existing symbol1139 // When both the to-bo-exported symbol and the already existing symbol
...@@ -1148,7 +1147,7 @@ pub fn updateDeclExports(...@@ -1148,7 +1147,7 @@ pub fn updateDeclExports(
1148 \\ first definition in '{s}'1147 \\ first definition in '{s}'
1149 \\ next definition in '{s}'1148 \\ next definition in '{s}'
1150 ,1149 ,
1151 .{ exp.options.name, self.name, self.name },1150 .{ exp.options.name, wasm.name, wasm.name },
1152 ));1151 ));
1153 continue;1152 continue;
1154 } else if (exp_is_weak) {1153 } else if (exp_is_weak) {
...@@ -1163,7 +1162,7 @@ pub fn updateDeclExports(...@@ -1163,7 +1162,7 @@ pub fn updateDeclExports(
1163 const exported_decl = mod.declPtr(exp.exported_decl);1162 const exported_decl = mod.declPtr(exp.exported_decl);
1164 const sym_index = exported_decl.link.wasm.sym_index;1163 const sym_index = exported_decl.link.wasm.sym_index;
1165 const sym_loc = exported_decl.link.wasm.symbolLoc();1164 const sym_loc = exported_decl.link.wasm.symbolLoc();
1166 const symbol = sym_loc.getSymbol(self);1165 const symbol = sym_loc.getSymbol(wasm);
1167 switch (exp.options.linkage) {1166 switch (exp.options.linkage) {
1168 .Internal => {1167 .Internal => {
1169 symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);1168 symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);
...@@ -1183,68 +1182,68 @@ pub fn updateDeclExports(...@@ -1183,68 +1182,68 @@ pub fn updateDeclExports(
1183 },1182 },
1184 }1183 }
1185 // Ensure the symbol will be exported using the given name1184 // Ensure the symbol will be exported using the given name
1186 if (!mem.eql(u8, exp.options.name, sym_loc.getName(self))) {1185 if (!mem.eql(u8, exp.options.name, sym_loc.getName(wasm))) {
1187 try self.export_names.put(self.base.allocator, sym_loc, export_name);1186 try wasm.export_names.put(wasm.base.allocator, sym_loc, export_name);
1188 }1187 }
11891188
1190 symbol.setGlobal(true);1189 symbol.setGlobal(true);
1191 symbol.setUndefined(false);1190 symbol.setUndefined(false);
1192 try self.globals.put(1191 try wasm.globals.put(
1193 self.base.allocator,1192 wasm.base.allocator,
1194 export_name,1193 export_name,
1195 sym_loc,1194 sym_loc,
1196 );1195 );
11971196
1198 // if the symbol was previously undefined, remove it as an import1197 // if the symbol was previously undefined, remove it as an import
1199 _ = self.imports.remove(sym_loc);1198 _ = wasm.imports.remove(sym_loc);
1200 _ = self.undefs.swapRemove(exp.options.name);1199 _ = wasm.undefs.swapRemove(exp.options.name);
1201 exp.link.wasm.sym_index = sym_index;1200 exp.link.wasm.sym_index = sym_index;
1202 }1201 }
1203}1202}
12041203
1205pub fn freeDecl(self: *Wasm, decl_index: Module.Decl.Index) void {1204pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {
1206 if (build_options.have_llvm) {1205 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);
1208 }1207 }
1209 const mod = self.base.options.module.?;1208 const mod = wasm.base.options.module.?;
1210 const decl = mod.declPtr(decl_index);1209 const decl = mod.declPtr(decl_index);
1211 const atom = &decl.link.wasm;1210 const atom = &decl.link.wasm;
1212 self.symbols_free_list.append(self.base.allocator, atom.sym_index) catch {};1211 wasm.symbols_free_list.append(wasm.base.allocator, atom.sym_index) catch {};
1213 _ = self.decls.remove(decl_index);1212 _ = wasm.decls.remove(decl_index);
1214 self.symbols.items[atom.sym_index].tag = .dead;1213 wasm.symbols.items[atom.sym_index].tag = .dead;
1215 for (atom.locals.items) |local_atom| {1214 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];
1217 local_symbol.tag = .dead; // also for any local symbol1216 local_symbol.tag = .dead; // also for any local symbol
1218 self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {};1217 wasm.symbols_free_list.append(wasm.base.allocator, local_atom.sym_index) catch {};
1219 assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc()));1218 assert(wasm.resolved_symbols.swapRemove(local_atom.symbolLoc()));
1220 assert(self.symbol_atom.remove(local_atom.symbolLoc()));1219 assert(wasm.symbol_atom.remove(local_atom.symbolLoc()));
1221 }1220 }
12221221
1223 if (decl.isExtern()) {1222 if (decl.isExtern()) {
1224 _ = self.imports.remove(atom.symbolLoc());1223 _ = wasm.imports.remove(atom.symbolLoc());
1225 }1224 }
1226 _ = self.resolved_symbols.swapRemove(atom.symbolLoc());1225 _ = wasm.resolved_symbols.swapRemove(atom.symbolLoc());
1227 _ = self.symbol_atom.remove(atom.symbolLoc());1226 _ = wasm.symbol_atom.remove(atom.symbolLoc());
12281227
1229 if (self.dwarf) |*dwarf| {1228 if (wasm.dwarf) |*dwarf| {
1230 dwarf.freeDecl(decl);1229 dwarf.freeDecl(decl);
1231 dwarf.freeAtom(&atom.dbg_info_atom);1230 dwarf.freeAtom(&atom.dbg_info_atom);
1232 }1231 }
12331232
1234 atom.deinit(self.base.allocator);1233 atom.deinit(wasm.base.allocator);
1235}1234}
12361235
1237/// Appends a new entry to the indirect function table1236/// Appends a new entry to the indirect function table
1238pub fn addTableFunction(self: *Wasm, symbol_index: u32) !void {1237pub fn addTableFunction(wasm: *Wasm, symbol_index: u32) !void {
1239 const index = @intCast(u32, self.function_table.count());1238 const index = @intCast(u32, wasm.function_table.count());
1240 try self.function_table.put(self.base.allocator, .{ .file = null, .index = symbol_index }, index);1239 try wasm.function_table.put(wasm.base.allocator, .{ .file = null, .index = symbol_index }, index);
1241}1240}
12421241
1243/// Assigns indexes to all indirect functions.1242/// Assigns indexes to all indirect functions.
1244/// Starts at offset 1, where the value `0` represents an unresolved function pointer1243/// Starts at offset 1, where the value `0` represents an unresolved function pointer
1245/// or null-pointer1244/// or null-pointer
1246fn mapFunctionTable(self: *Wasm) void {1245fn mapFunctionTable(wasm: *Wasm) void {
1247 var it = self.function_table.valueIterator();1246 var it = wasm.function_table.valueIterator();
1248 var index: u32 = 1;1247 var index: u32 = 1;
1249 while (it.next()) |value_ptr| : (index += 1) {1248 while (it.next()) |value_ptr| : (index += 1) {
1250 value_ptr.* = index;1249 value_ptr.* = index;
...@@ -1255,7 +1254,7 @@ fn mapFunctionTable(self: *Wasm) void {...@@ -1255,7 +1254,7 @@ fn mapFunctionTable(self: *Wasm) void {
1255/// When `type_index` is non-null, we assume an external function.1254/// When `type_index` is non-null, we assume an external function.
1256/// In all other cases, a data-symbol will be created instead.1255/// In all other cases, a data-symbol will be created instead.
1257pub fn addOrUpdateImport(1256pub fn addOrUpdateImport(
1258 self: *Wasm,1257 wasm: *Wasm,
1259 /// Name of the import1258 /// Name of the import
1260 name: []const u8,1259 name: []const u8,
1261 /// Symbol index that is external1260 /// Symbol index that is external
...@@ -1268,28 +1267,28 @@ pub fn addOrUpdateImport(...@@ -1268,28 +1267,28 @@ pub fn addOrUpdateImport(
1268 type_index: ?u32,1267 type_index: ?u32,
1269) !void {1268) !void {
1270 assert(symbol_index != 0);1269 assert(symbol_index != 0);
1271 // For the import name itself, we use the decl's name, rather than the fully qualified name1270 // For the import name itwasm, 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);1271 const decl_name_index = try wasm.string_table.put(wasm.base.allocator, name);
1273 const symbol: *Symbol = &self.symbols.items[symbol_index];1272 const symbol: *Symbol = &wasm.symbols.items[symbol_index];
1274 symbol.setUndefined(true);1273 symbol.setUndefined(true);
1275 symbol.setGlobal(true);1274 symbol.setGlobal(true);
1276 symbol.name = decl_name_index;1275 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);
1278 if (!global_gop.found_existing) {1277 if (!global_gop.found_existing) {
1279 const loc: SymbolLoc = .{ .file = null, .index = symbol_index };1278 const loc: SymbolLoc = .{ .file = null, .index = symbol_index };
1280 global_gop.value_ptr.* = loc;1279 global_gop.value_ptr.* = loc;
1281 try self.resolved_symbols.put(self.base.allocator, loc, {});1280 try wasm.resolved_symbols.put(wasm.base.allocator, loc, {});
1282 try self.undefs.putNoClobber(self.base.allocator, name, loc);1281 try wasm.undefs.putNoClobber(wasm.base.allocator, name, loc);
1283 }1282 }
12841283
1285 if (type_index) |ty_index| {1284 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 });
1287 const module_name = if (lib_name) |l_name| blk: {1286 const module_name = if (lib_name) |l_name| blk: {
1288 break :blk mem.sliceTo(l_name, 0);1287 break :blk mem.sliceTo(l_name, 0);
1289 } else self.host_name;1288 } else wasm.host_name;
1290 if (!gop.found_existing) {1289 if (!gop.found_existing) {
1291 gop.value_ptr.* = .{1290 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),
1293 .name = decl_name_index,1292 .name = decl_name_index,
1294 .kind = .{ .function = ty_index },1293 .kind = .{ .function = ty_index },
1295 };1294 };
...@@ -1326,36 +1325,36 @@ const Kind = union(enum) {...@@ -1326,36 +1325,36 @@ const Kind = union(enum) {
1326};1325};
13271326
1328/// Parses an Atom and inserts its metadata into the corresponding sections.1327/// Parses an Atom and inserts its metadata into the corresponding sections.
1329fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void {1328fn parseAtom(wasm: *Wasm, atom: *Atom, kind: Kind) !void {
1330 const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(self);1329 const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm);
1331 const final_index: u32 = switch (kind) {1330 const final_index: u32 = switch (kind) {
1332 .function => |fn_data| result: {1331 .function => |fn_data| result: {
1333 const index = @intCast(u32, self.functions.count() + self.imported_functions_count);1332 const index = @intCast(u32, wasm.functions.count() + wasm.imported_functions_count);
1334 try self.functions.putNoClobber(1333 try wasm.functions.putNoClobber(
1335 self.base.allocator,1334 wasm.base.allocator,
1336 .{ .file = null, .index = index },1335 .{ .file = null, .index = index },
1337 .{ .type_index = fn_data.type_index },1336 .{ .type_index = fn_data.type_index },
1338 );1337 );
1339 symbol.tag = .function;1338 symbol.tag = .function;
1340 symbol.index = index;1339 symbol.index = index;
13411340
1342 if (self.code_section_index == null) {1341 if (wasm.code_section_index == null) {
1343 self.code_section_index = @intCast(u32, self.segments.items.len);1342 wasm.code_section_index = @intCast(u32, wasm.segments.items.len);
1344 try self.segments.append(self.base.allocator, .{1343 try wasm.segments.append(wasm.base.allocator, .{
1345 .alignment = atom.alignment,1344 .alignment = atom.alignment,
1346 .size = atom.size,1345 .size = atom.size,
1347 .offset = 0,1346 .offset = 0,
1348 });1347 });
1349 }1348 }
13501349
1351 break :result self.code_section_index.?;1350 break :result wasm.code_section_index.?;
1352 },1351 },
1353 .data => result: {1352 .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, &.{
1355 kind.segmentName(),1354 kind.segmentName(),
1356 self.string_table.get(symbol.name),1355 wasm.string_table.get(symbol.name),
1357 });1356 });
1358 errdefer self.base.allocator.free(segment_name);1357 errdefer wasm.base.allocator.free(segment_name);
1359 const segment_info: types.Segment = .{1358 const segment_info: types.Segment = .{
1360 .name = segment_name,1359 .name = segment_name,
1361 .alignment = atom.alignment,1360 .alignment = atom.alignment,
...@@ -1367,59 +1366,59 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void {...@@ -1367,59 +1366,59 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void {
1367 // we set the entire region of it to zeroes.1366 // we set the entire region of it to zeroes.
1368 // We do not have to do this when exporting the memory (the default) because the runtime1367 // We do not have to do this when exporting the memory (the default) because the runtime
1369 // will do it for us, and we do not emit the bss segment at all.1368 // 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) {
1371 std.mem.set(u8, atom.code.items, 0);1370 std.mem.set(u8, atom.code.items, 0);
1372 }1371 }
13731372
1374 const should_merge = self.base.options.output_mode != .Obj;1373 const should_merge = wasm.base.options.output_mode != .Obj;
1375 const gop = try self.data_segments.getOrPut(self.base.allocator, segment_info.outputName(should_merge));1374 const gop = try wasm.data_segments.getOrPut(wasm.base.allocator, segment_info.outputName(should_merge));
1376 if (gop.found_existing) {1375 if (gop.found_existing) {
1377 const index = gop.value_ptr.*;1376 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).?);
1381 // segment info already exists, so free its memory1380 // segment info already exists, so free its memory
1382 self.base.allocator.free(segment_name);1381 wasm.base.allocator.free(segment_name);
1383 break :result index;1382 break :result index;
1384 } else {1383 } else {
1385 const index = @intCast(u32, self.segments.items.len);1384 const index = @intCast(u32, wasm.segments.items.len);
1386 try self.segments.append(self.base.allocator, .{1385 try wasm.segments.append(wasm.base.allocator, .{
1387 .alignment = atom.alignment,1386 .alignment = atom.alignment,
1388 .size = 0,1387 .size = 0,
1389 .offset = 0,1388 .offset = 0,
1390 });1389 });
1391 gop.value_ptr.* = index;1390 gop.value_ptr.* = index;
13921391
1393 const info_index = @intCast(u32, self.segment_info.count());1392 const info_index = @intCast(u32, wasm.segment_info.count());
1394 try self.segment_info.put(self.base.allocator, index, segment_info);1393 try wasm.segment_info.put(wasm.base.allocator, index, segment_info);
1395 symbol.index = info_index;1394 symbol.index = info_index;
1396 break :result index;1395 break :result index;
1397 }1396 }
1398 },1397 },
1399 };1398 };
14001399
1401 const segment: *Segment = &self.segments.items[final_index];1400 const segment: *Segment = &wasm.segments.items[final_index];
1402 segment.alignment = std.math.max(segment.alignment, atom.alignment);1401 segment.alignment = std.math.max(segment.alignment, atom.alignment);
14031402
1404 try self.appendAtomAtIndex(final_index, atom);1403 try wasm.appendAtomAtIndex(final_index, atom);
1405}1404}
14061405
1407/// From a given index, append the given `Atom` at the back of the linked list.1406/// From a given index, append the given `Atom` at the back of the linked list.
1408/// Simply inserts it into the map of atoms when it doesn't exist yet.1407/// Simply inserts it into the map of atoms when it doesn't exist yet.
1409pub fn appendAtomAtIndex(self: *Wasm, index: u32, atom: *Atom) !void {1408pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom: *Atom) !void {
1410 if (self.atoms.getPtr(index)) |last| {1409 if (wasm.atoms.getPtr(index)) |last| {
1411 last.*.next = atom;1410 last.*.next = atom;
1412 atom.prev = last.*;1411 atom.prev = last.*;
1413 last.* = atom;1412 last.* = atom;
1414 } else {1413 } else {
1415 try self.atoms.putNoClobber(self.base.allocator, index, atom);1414 try wasm.atoms.putNoClobber(wasm.base.allocator, index, atom);
1416 }1415 }
1417}1416}
14181417
1419/// Allocates debug atoms into their respective debug sections1418/// Allocates debug atoms into their respective debug sections
1420/// to merge them with maybe-existing debug atoms from object files.1419/// to merge them with maybe-existing debug atoms from object files.
1421fn allocateDebugAtoms(self: *Wasm) !void {1420fn allocateDebugAtoms(wasm: *Wasm) !void {
1422 if (self.dwarf == null) return;1421 if (wasm.dwarf == null) return;
14231422
1424 const allocAtom = struct {1423 const allocAtom = struct {
1425 fn f(bin: *Wasm, maybe_index: *?u32, atom: *Atom) !void {1424 fn f(bin: *Wasm, maybe_index: *?u32, atom: *Atom) !void {
...@@ -1435,24 +1434,24 @@ fn allocateDebugAtoms(self: *Wasm) !void {...@@ -1435,24 +1434,24 @@ fn allocateDebugAtoms(self: *Wasm) !void {
1435 }1434 }
1436 }.f;1435 }.f;
14371436
1438 try allocAtom(self, &self.debug_info_index, self.debug_info_atom.?);1437 try allocAtom(wasm, &wasm.debug_info_index, wasm.debug_info_atom.?);
1439 try allocAtom(self, &self.debug_line_index, self.debug_line_atom.?);1438 try allocAtom(wasm, &wasm.debug_line_index, wasm.debug_line_atom.?);
1440 try allocAtom(self, &self.debug_loc_index, self.debug_loc_atom.?);1439 try allocAtom(wasm, &wasm.debug_loc_index, wasm.debug_loc_atom.?);
1441 try allocAtom(self, &self.debug_str_index, self.debug_str_atom.?);1440 try allocAtom(wasm, &wasm.debug_str_index, wasm.debug_str_atom.?);
1442 try allocAtom(self, &self.debug_ranges_index, self.debug_ranges_atom.?);1441 try allocAtom(wasm, &wasm.debug_ranges_index, wasm.debug_ranges_atom.?);
1443 try allocAtom(self, &self.debug_abbrev_index, self.debug_abbrev_atom.?);1442 try allocAtom(wasm, &wasm.debug_abbrev_index, wasm.debug_abbrev_atom.?);
1444 try allocAtom(self, &self.debug_pubnames_index, self.debug_pubnames_atom.?);1443 try allocAtom(wasm, &wasm.debug_pubnames_index, wasm.debug_pubnames_atom.?);
1445 try allocAtom(self, &self.debug_pubtypes_index, self.debug_pubtypes_atom.?);1444 try allocAtom(wasm, &wasm.debug_pubtypes_index, wasm.debug_pubtypes_atom.?);
1446}1445}
14471446
1448fn allocateAtoms(self: *Wasm) !void {1447fn allocateAtoms(wasm: *Wasm) !void {
1449 // first sort the data segments1448 // first sort the data segments
1450 try sortDataSegments(self);1449 try sortDataSegments(wasm);
1451 try allocateDebugAtoms(self);1450 try allocateDebugAtoms(wasm);
14521451
1453 var it = self.atoms.iterator();1452 var it = wasm.atoms.iterator();
1454 while (it.next()) |entry| {1453 while (it.next()) |entry| {
1455 const segment = &self.segments.items[entry.key_ptr.*];1454 const segment = &wasm.segments.items[entry.key_ptr.*];
1456 var atom: *Atom = entry.value_ptr.*.getFirst();1455 var atom: *Atom = entry.value_ptr.*.getFirst();
1457 var offset: u32 = 0;1456 var offset: u32 = 0;
1458 while (true) {1457 while (true) {
...@@ -1460,26 +1459,26 @@ fn allocateAtoms(self: *Wasm) !void {...@@ -1460,26 +1459,26 @@ fn allocateAtoms(self: *Wasm) !void {
1460 atom.offset = offset;1459 atom.offset = offset;
1461 const symbol_loc = atom.symbolLoc();1460 const symbol_loc = atom.symbolLoc();
1462 log.debug("Atom '{s}' allocated from 0x{x:0>8} to 0x{x:0>8} size={d}", .{1461 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),
1464 offset,1463 offset,
1465 offset + atom.size,1464 offset + atom.size,
1466 atom.size,1465 atom.size,
1467 });1466 });
1468 offset += atom.size;1467 offset += atom.size;
1469 try self.symbol_atom.put(self.base.allocator, atom.symbolLoc(), atom); // Update atom pointers1468 try wasm.symbol_atom.put(wasm.base.allocator, atom.symbolLoc(), atom); // Update atom pointers
1470 atom = atom.next orelse break;1469 atom = atom.next orelse break;
1471 }1470 }
1472 segment.size = std.mem.alignForwardGeneric(u32, offset, segment.alignment);1471 segment.size = std.mem.alignForwardGeneric(u32, offset, segment.alignment);
1473 }1472 }
1474}1473}
14751474
1476fn sortDataSegments(self: *Wasm) !void {1475fn sortDataSegments(wasm: *Wasm) !void {
1477 var new_mapping: std.StringArrayHashMapUnmanaged(u32) = .{};1476 var new_mapping: std.StringArrayHashMapUnmanaged(u32) = .{};
1478 try new_mapping.ensureUnusedCapacity(self.base.allocator, self.data_segments.count());1477 try new_mapping.ensureUnusedCapacity(wasm.base.allocator, wasm.data_segments.count());
1479 errdefer new_mapping.deinit(self.base.allocator);1478 errdefer new_mapping.deinit(wasm.base.allocator);
14801479
1481 const keys = try self.base.allocator.dupe([]const u8, self.data_segments.keys());1480 const keys = try wasm.base.allocator.dupe([]const u8, wasm.data_segments.keys());
1482 defer self.base.allocator.free(keys);1481 defer wasm.base.allocator.free(keys);
14831482
1484 const SortContext = struct {1483 const SortContext = struct {
1485 fn sort(_: void, lhs: []const u8, rhs: []const u8) bool {1484 fn sort(_: void, lhs: []const u8, rhs: []const u8) bool {
...@@ -1496,63 +1495,63 @@ fn sortDataSegments(self: *Wasm) !void {...@@ -1496,63 +1495,63 @@ fn sortDataSegments(self: *Wasm) !void {
14961495
1497 std.sort.sort([]const u8, keys, {}, SortContext.sort);1496 std.sort.sort([]const u8, keys, {}, SortContext.sort);
1498 for (keys) |key| {1497 for (keys) |key| {
1499 const segment_index = self.data_segments.get(key).?;1498 const segment_index = wasm.data_segments.get(key).?;
1500 new_mapping.putAssumeCapacity(key, segment_index);1499 new_mapping.putAssumeCapacity(key, segment_index);
1501 }1500 }
1502 self.data_segments.deinit(self.base.allocator);1501 wasm.data_segments.deinit(wasm.base.allocator);
1503 self.data_segments = new_mapping;1502 wasm.data_segments = new_mapping;
1504}1503}
15051504
1506fn setupImports(self: *Wasm) !void {1505fn setupImports(wasm: *Wasm) !void {
1507 log.debug("Merging imports", .{});1506 log.debug("Merging imports", .{});
1508 var discarded_it = self.discarded.keyIterator();1507 var discarded_it = wasm.discarded.keyIterator();
1509 while (discarded_it.next()) |discarded| {1508 while (discarded_it.next()) |discarded| {
1510 if (discarded.file == null) {1509 if (discarded.file == null) {
1511 // remove an import if it was resolved1510 // remove an import if it was resolved
1512 if (self.imports.remove(discarded.*)) {1511 if (wasm.imports.remove(discarded.*)) {
1513 log.debug("Removed symbol '{s}' as an import", .{1512 log.debug("Removed symbol '{s}' as an import", .{
1514 discarded.getName(self),1513 discarded.getName(wasm),
1515 });1514 });
1516 }1515 }
1517 }1516 }
1518 }1517 }
15191518
1520 for (self.resolved_symbols.keys()) |symbol_loc| {1519 for (wasm.resolved_symbols.keys()) |symbol_loc| {
1521 if (symbol_loc.file == null) {1520 if (symbol_loc.file == null) {
1522 // imports generated by Zig code are already in the `import` section1521 // imports generated by Zig code are already in the `import` section
1523 continue;1522 continue;
1524 }1523 }
15251524
1526 const symbol = symbol_loc.getSymbol(self);1525 const symbol = symbol_loc.getSymbol(wasm);
1527 if (std.mem.eql(u8, symbol_loc.getName(self), "__indirect_function_table")) {1526 if (std.mem.eql(u8, symbol_loc.getName(wasm), "__indirect_function_table")) {
1528 continue;1527 continue;
1529 }1528 }
1530 if (!symbol.requiresImport()) {1529 if (!symbol.requiresImport()) {
1531 continue;1530 continue;
1532 }1531 }
15331532
1534 log.debug("Symbol '{s}' will be imported from the host", .{symbol_loc.getName(self)});1533 log.debug("Symbol '{s}' will be imported from the host", .{symbol_loc.getName(wasm)});
1535 const object = self.objects.items[symbol_loc.file.?];1534 const object = wasm.objects.items[symbol_loc.file.?];
1536 const import = object.findImport(symbol.tag.externalType(), symbol.index);1535 const import = object.findImport(symbol.tag.externalType(), symbol.index);
15371536
1538 // We copy the import to a new import to ensure the names contain references1537 // We copy the import to a new import to ensure the names contain references
1539 // to the internal string table, rather than of the object file.1538 // to the internal string table, rather than of the object file.
1540 var new_imp: types.Import = .{1539 var new_imp: types.Import = .{
1541 .module_name = try self.string_table.put(self.base.allocator, object.string_table.get(import.module_name)),1540 .module_name = try wasm.string_table.put(wasm.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)),1541 .name = try wasm.string_table.put(wasm.base.allocator, object.string_table.get(import.name)),
1543 .kind = import.kind,1542 .kind = import.kind,
1544 };1543 };
1545 // TODO: De-duplicate imports when they contain the same names and type1544 // 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);
1547 }1546 }
15481547
1549 // Assign all indexes of the imports to their representing symbols1548 // Assign all indexes of the imports to their representing symbols
1550 var function_index: u32 = 0;1549 var function_index: u32 = 0;
1551 var global_index: u32 = 0;1550 var global_index: u32 = 0;
1552 var table_index: u32 = 0;1551 var table_index: u32 = 0;
1553 var it = self.imports.iterator();1552 var it = wasm.imports.iterator();
1554 while (it.next()) |entry| {1553 while (it.next()) |entry| {
1555 const symbol = entry.key_ptr.*.getSymbol(self);1554 const symbol = entry.key_ptr.*.getSymbol(wasm);
1556 const import: types.Import = entry.value_ptr.*;1555 const import: types.Import = entry.value_ptr.*;
1557 switch (import.kind) {1556 switch (import.kind) {
1558 .function => {1557 .function => {
...@@ -1570,9 +1569,9 @@ fn setupImports(self: *Wasm) !void {...@@ -1570,9 +1569,9 @@ fn setupImports(self: *Wasm) !void {
1570 else => unreachable,1569 else => unreachable,
1571 }1570 }
1572 }1571 }
1573 self.imported_functions_count = function_index;1572 wasm.imported_functions_count = function_index;
1574 self.imported_globals_count = global_index;1573 wasm.imported_globals_count = global_index;
1575 self.imported_tables_count = table_index;1574 wasm.imported_tables_count = table_index;
15761575
1577 log.debug("Merged ({d}) functions, ({d}) globals, and ({d}) tables into import section", .{1576 log.debug("Merged ({d}) functions, ({d}) globals, and ({d}) tables into import section", .{
1578 function_index,1577 function_index,
...@@ -1583,26 +1582,26 @@ fn setupImports(self: *Wasm) !void {...@@ -1583,26 +1582,26 @@ fn setupImports(self: *Wasm) !void {
15831582
1584/// Takes the global, function and table section from each linked object file1583/// Takes the global, function and table section from each linked object file
1585/// and merges it into a single section for each.1584/// and merges it into a single section for each.
1586fn mergeSections(self: *Wasm) !void {1585fn mergeSections(wasm: *Wasm) !void {
1587 // append the indirect function table if initialized1586 // append the indirect function table if initialized
1588 if (self.string_table.getOffset("__indirect_function_table")) |offset| {1587 if (wasm.string_table.getOffset("__indirect_function_table")) |offset| {
1589 const sym_loc = self.globals.get(offset).?;1588 const sym_loc = wasm.globals.get(offset).?;
1590 const table: wasm.Table = .{1589 const table: std.wasm.Table = .{
1591 .limits = .{ .min = @intCast(u32, self.function_table.count()), .max = null },1590 .limits = .{ .min = @intCast(u32, wasm.function_table.count()), .max = null },
1592 .reftype = .funcref,1591 .reftype = .funcref,
1593 };1592 };
1594 sym_loc.getSymbol(self).index = @intCast(u32, self.tables.items.len) + self.imported_tables_count;1593 sym_loc.getSymbol(wasm).index = @intCast(u32, wasm.tables.items.len) + wasm.imported_tables_count;
1595 try self.tables.append(self.base.allocator, table);1594 try wasm.tables.append(wasm.base.allocator, table);
1596 }1595 }
15971596
1598 for (self.resolved_symbols.keys()) |sym_loc| {1597 for (wasm.resolved_symbols.keys()) |sym_loc| {
1599 if (sym_loc.file == null) {1598 if (sym_loc.file == null) {
1600 // Zig code-generated symbols are already within the sections and do not1599 // Zig code-generated symbols are already within the sections and do not
1601 // require to be merged1600 // require to be merged
1602 continue;1601 continue;
1603 }1602 }
16041603
1605 const object = self.objects.items[sym_loc.file.?];1604 const object = wasm.objects.items[sym_loc.file.?];
1606 const symbol = &object.symtable[sym_loc.index];1605 const symbol = &object.symtable[sym_loc.index];
1607 if (symbol.isUndefined() or (symbol.tag != .function and symbol.tag != .global and symbol.tag != .table)) {1606 if (symbol.isUndefined() or (symbol.tag != .function and symbol.tag != .global and symbol.tag != .table)) {
1608 // Skip undefined symbols as they go in the `import` section1607 // Skip undefined symbols as they go in the `import` section
...@@ -1615,51 +1614,51 @@ fn mergeSections(self: *Wasm) !void {...@@ -1615,51 +1614,51 @@ fn mergeSections(self: *Wasm) !void {
1615 switch (symbol.tag) {1614 switch (symbol.tag) {
1616 .function => {1615 .function => {
1617 const original_func = object.functions[index];1616 const original_func = object.functions[index];
1618 const gop = try self.functions.getOrPut(1617 const gop = try wasm.functions.getOrPut(
1619 self.base.allocator,1618 wasm.base.allocator,
1620 .{ .file = sym_loc.file, .index = symbol.index },1619 .{ .file = sym_loc.file, .index = symbol.index },
1621 );1620 );
1622 if (!gop.found_existing) {1621 if (!gop.found_existing) {
1623 gop.value_ptr.* = original_func;1622 gop.value_ptr.* = original_func;
1624 }1623 }
1625 symbol.index = @intCast(u32, gop.index) + self.imported_functions_count;1624 symbol.index = @intCast(u32, gop.index) + wasm.imported_functions_count;
1626 },1625 },
1627 .global => {1626 .global => {
1628 const original_global = object.globals[index];1627 const original_global = object.globals[index];
1629 symbol.index = @intCast(u32, self.wasm_globals.items.len) + self.imported_globals_count;1628 symbol.index = @intCast(u32, wasm.wasm_globals.items.len) + wasm.imported_globals_count;
1630 try self.wasm_globals.append(self.base.allocator, original_global);1629 try wasm.wasm_globals.append(wasm.base.allocator, original_global);
1631 },1630 },
1632 .table => {1631 .table => {
1633 const original_table = object.tables[index];1632 const original_table = object.tables[index];
1634 symbol.index = @intCast(u32, self.tables.items.len) + self.imported_tables_count;1633 symbol.index = @intCast(u32, wasm.tables.items.len) + wasm.imported_tables_count;
1635 try self.tables.append(self.base.allocator, original_table);1634 try wasm.tables.append(wasm.base.allocator, original_table);
1636 },1635 },
1637 else => unreachable,1636 else => unreachable,
1638 }1637 }
1639 }1638 }
16401639
1641 log.debug("Merged ({d}) functions", .{self.functions.count()});1640 log.debug("Merged ({d}) functions", .{wasm.functions.count()});
1642 log.debug("Merged ({d}) globals", .{self.wasm_globals.items.len});1641 log.debug("Merged ({d}) globals", .{wasm.wasm_globals.items.len});
1643 log.debug("Merged ({d}) tables", .{self.tables.items.len});1642 log.debug("Merged ({d}) tables", .{wasm.tables.items.len});
1644}1643}
16451644
1646/// Merges function types of all object files into the final1645/// Merges function types of all object files into the final
1647/// 'types' section, while assigning the type index to the representing1646/// 'types' section, while assigning the type index to the representing
1648/// section (import, export, function).1647/// section (import, export, function).
1649fn mergeTypes(self: *Wasm) !void {1648fn mergeTypes(wasm: *Wasm) !void {
1650 // A map to track which functions have already had their1649 // A map to track which functions have already had their
1651 // type inserted. If we do this for the same function multiple times,1650 // type inserted. If we do this for the same function multiple times,
1652 // it will be overwritten with the incorrect type.1651 // it will be overwritten with the incorrect type.
1653 var dirty = std.AutoHashMap(u32, void).init(self.base.allocator);1652 var dirty = std.AutoHashMap(u32, void).init(wasm.base.allocator);
1654 try dirty.ensureUnusedCapacity(@intCast(u32, self.functions.count()));1653 try dirty.ensureUnusedCapacity(@intCast(u32, wasm.functions.count()));
1655 defer dirty.deinit();1654 defer dirty.deinit();
16561655
1657 for (self.resolved_symbols.keys()) |sym_loc| {1656 for (wasm.resolved_symbols.keys()) |sym_loc| {
1658 if (sym_loc.file == null) {1657 if (sym_loc.file == null) {
1659 // zig code-generated symbols are already present in final type section1658 // zig code-generated symbols are already present in final type section
1660 continue;1659 continue;
1661 }1660 }
1662 const object = self.objects.items[sym_loc.file.?];1661 const object = wasm.objects.items[sym_loc.file.?];
1663 const symbol = object.symtable[sym_loc.index];1662 const symbol = object.symtable[sym_loc.index];
1664 if (symbol.tag != .function) {1663 if (symbol.tag != .function) {
1665 // Only functions have types1664 // Only functions have types
...@@ -1667,32 +1666,32 @@ fn mergeTypes(self: *Wasm) !void {...@@ -1667,32 +1666,32 @@ fn mergeTypes(self: *Wasm) !void {
1667 }1666 }
16681667
1669 if (symbol.isUndefined()) {1668 if (symbol.isUndefined()) {
1670 log.debug("Adding type from extern function '{s}'", .{sym_loc.getName(self)});1669 log.debug("Adding type from extern function '{s}'", .{sym_loc.getName(wasm)});
1671 const import: *types.Import = self.imports.getPtr(sym_loc).?;1670 const import: *types.Import = wasm.imports.getPtr(sym_loc).?;
1672 const original_type = object.func_types[import.kind.function];1671 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);
1674 } else if (!dirty.contains(symbol.index)) {1673 } else if (!dirty.contains(symbol.index)) {
1675 log.debug("Adding type from function '{s}'", .{sym_loc.getName(self)});1674 log.debug("Adding type from function '{s}'", .{sym_loc.getName(wasm)});
1676 const func = &self.functions.values()[symbol.index - self.imported_functions_count];1675 const func = &wasm.functions.values()[symbol.index - wasm.imported_functions_count];
1677 func.type_index = try self.putOrGetFuncType(object.func_types[func.type_index]);1676 func.type_index = try wasm.putOrGetFuncType(object.func_types[func.type_index]);
1678 dirty.putAssumeCapacityNoClobber(symbol.index, {});1677 dirty.putAssumeCapacityNoClobber(symbol.index, {});
1679 }1678 }
1680 }1679 }
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});
1682}1681}
16831682
1684fn setupExports(self: *Wasm) !void {1683fn setupExports(wasm: *Wasm) !void {
1685 if (self.base.options.output_mode == .Obj) return;1684 if (wasm.base.options.output_mode == .Obj) return;
1686 log.debug("Building exports from symbols", .{});1685 log.debug("Building exports from symbols", .{});
16871686
1688 for (self.resolved_symbols.keys()) |sym_loc| {1687 for (wasm.resolved_symbols.keys()) |sym_loc| {
1689 const symbol = sym_loc.getSymbol(self);1688 const symbol = sym_loc.getSymbol(wasm);
1690 if (!symbol.isExported()) continue;1689 if (!symbol.isExported()) continue;
16911690
1692 const sym_name = sym_loc.getName(self);1691 const sym_name = sym_loc.getName(wasm);
1693 const export_name = if (self.export_names.get(sym_loc)) |name| name else blk: {1692 const export_name = if (wasm.export_names.get(sym_loc)) |name| name else blk: {
1694 if (sym_loc.file == null) break :blk symbol.name;1693 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);
1696 };1695 };
1697 const exp: types.Export = .{1696 const exp: types.Export = .{
1698 .name = export_name,1697 .name = export_name,
...@@ -1701,21 +1700,21 @@ fn setupExports(self: *Wasm) !void {...@@ -1701,21 +1700,21 @@ fn setupExports(self: *Wasm) !void {
1701 };1700 };
1702 log.debug("Exporting symbol '{s}' as '{s}' at index: ({d})", .{1701 log.debug("Exporting symbol '{s}' as '{s}' at index: ({d})", .{
1703 sym_name,1702 sym_name,
1704 self.string_table.get(exp.name),1703 wasm.string_table.get(exp.name),
1705 exp.index,1704 exp.index,
1706 });1705 });
1707 try self.exports.append(self.base.allocator, exp);1706 try wasm.exports.append(wasm.base.allocator, exp);
1708 }1707 }
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});
1711}1710}
17121711
1713fn setupStart(self: *Wasm) !void {1712fn setupStart(wasm: *Wasm) !void {
1714 const entry_name = self.base.options.entry orelse "_start";1713 const entry_name = wasm.base.options.entry orelse "_start";
17151714
1716 const symbol_name_offset = self.string_table.getOffset(entry_name) orelse {1715 const symbol_name_offset = wasm.string_table.getOffset(entry_name) orelse {
1717 if (self.base.options.output_mode == .Exe) {1716 if (wasm.base.options.output_mode == .Exe) {
1718 if (self.base.options.wasi_exec_model == .reactor) return; // Not required for reactors1717 if (wasm.base.options.wasi_exec_model == .reactor) return; // Not required for reactors
1719 } else {1718 } else {
1720 return; // No entry point needed for non-executable wasm files1719 return; // No entry point needed for non-executable wasm files
1721 }1720 }
...@@ -1723,45 +1722,45 @@ fn setupStart(self: *Wasm) !void {...@@ -1723,45 +1722,45 @@ fn setupStart(self: *Wasm) !void {
1723 return error.MissingSymbol;1722 return error.MissingSymbol;
1724 };1723 };
17251724
1726 const symbol_loc = self.globals.get(symbol_name_offset).?;1725 const symbol_loc = wasm.globals.get(symbol_name_offset).?;
1727 const symbol = symbol_loc.getSymbol(self);1726 const symbol = symbol_loc.getSymbol(wasm);
1728 if (symbol.tag != .function) {1727 if (symbol.tag != .function) {
1729 log.err("Entry symbol '{s}' is not a function", .{entry_name});1728 log.err("Entry symbol '{s}' is not a function", .{entry_name});
1730 return error.InvalidEntryKind;1729 return error.InvalidEntryKind;
1731 }1730 }
17321731
1733 // Ensure the symbol is exported so host environment can access it1732 // 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) {
1735 symbol.setFlag(.WASM_SYM_EXPORTED);1734 symbol.setFlag(.WASM_SYM_EXPORTED);
1736 }1735 }
1737}1736}
17381737
1739/// Sets up the memory section of the wasm module, as well as the stack.1738/// Sets up the memory section of the wasm module, as well as the stack.
1740fn setupMemory(self: *Wasm) !void {1739fn setupMemory(wasm: *Wasm) !void {
1741 log.debug("Setting up memory layout", .{});1740 log.debug("Setting up memory layout", .{});
1742 const page_size = 64 * 1024;1741 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;
1744 const stack_alignment = 16; // wasm's stack alignment as specified by tool-convention1743 const stack_alignment = 16; // wasm's stack alignment as specified by tool-convention
1745 // Always place the stack at the start by default1744 // Always place the stack at the start by default
1746 // unless the user specified the global-base flag1745 // unless the user specified the global-base flag
1747 var place_stack_first = true;1746 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: {
1749 place_stack_first = false;1748 place_stack_first = false;
1750 break :blk base;1749 break :blk base;
1751 } else 0;1750 } else 0;
17521751
1753 const is_obj = self.base.options.output_mode == .Obj;1752 const is_obj = wasm.base.options.output_mode == .Obj;
17541753
1755 if (place_stack_first and !is_obj) {1754 if (place_stack_first and !is_obj) {
1756 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment);1755 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment);
1757 memory_ptr += stack_size;1756 memory_ptr += stack_size;
1758 // We always put the stack pointer global at index 01757 // 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));
1760 }1759 }
17611760
1762 var offset: u32 = @intCast(u32, memory_ptr);1761 var offset: u32 = @intCast(u32, memory_ptr);
1763 for (self.data_segments.values()) |segment_index| {1762 for (wasm.data_segments.values()) |segment_index| {
1764 const segment = &self.segments.items[segment_index];1763 const segment = &wasm.segments.items[segment_index];
1765 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, segment.alignment);1764 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, segment.alignment);
1766 memory_ptr += segment.size;1765 memory_ptr += segment.size;
1767 segment.offset = offset;1766 segment.offset = offset;
...@@ -1771,14 +1770,14 @@ fn setupMemory(self: *Wasm) !void {...@@ -1771,14 +1770,14 @@ fn setupMemory(self: *Wasm) !void {
1771 if (!place_stack_first and !is_obj) {1770 if (!place_stack_first and !is_obj) {
1772 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment);1771 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment);
1773 memory_ptr += stack_size;1772 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));
1775 }1774 }
17761775
1777 // Setup the max amount of pages1776 // Setup the max amount of pages
1778 // For now we only support wasm32 by setting the maximum allowed memory size 2^32-11777 // For now we only support wasm32 by setting the maximum allowed memory size 2^32-1
1779 const max_memory_allowed: u64 = (1 << 32) - 1;1778 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| {
1782 if (!std.mem.isAlignedGeneric(u64, initial_memory, page_size)) {1781 if (!std.mem.isAlignedGeneric(u64, initial_memory, page_size)) {
1783 log.err("Initial memory must be {d}-byte aligned", .{page_size});1782 log.err("Initial memory must be {d}-byte aligned", .{page_size});
1784 return error.MissAlignment;1783 return error.MissAlignment;
...@@ -1796,10 +1795,10 @@ fn setupMemory(self: *Wasm) !void {...@@ -1796,10 +1795,10 @@ fn setupMemory(self: *Wasm) !void {
17961795
1797 // In case we do not import memory, but define it ourselves,1796 // In case we do not import memory, but define it ourselves,
1798 // set the minimum amount of pages on the memory section.1797 // 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);1798 wasm.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});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| {
1803 if (!std.mem.isAlignedGeneric(u64, max_memory, page_size)) {1802 if (!std.mem.isAlignedGeneric(u64, max_memory, page_size)) {
1804 log.err("Maximum memory must be {d}-byte aligned", .{page_size});1803 log.err("Maximum memory must be {d}-byte aligned", .{page_size});
1805 return error.MissAlignment;1804 return error.MissAlignment;
...@@ -1812,83 +1811,83 @@ fn setupMemory(self: *Wasm) !void {...@@ -1812,83 +1811,83 @@ fn setupMemory(self: *Wasm) !void {
1812 log.err("Maximum memory exceeds maxmium amount {d}", .{max_memory_allowed});1811 log.err("Maximum memory exceeds maxmium amount {d}", .{max_memory_allowed});
1813 return error.MemoryTooBig;1812 return error.MemoryTooBig;
1814 }1813 }
1815 self.memories.limits.max = @intCast(u32, max_memory / page_size);1814 wasm.memories.limits.max = @intCast(u32, max_memory / page_size);
1816 log.debug("Maximum memory pages: {?d}", .{self.memories.limits.max});1815 log.debug("Maximum memory pages: {?d}", .{wasm.memories.limits.max});
1817 }1816 }
1818}1817}
18191818
1820/// From a given object's index and the index of the segment, returns the corresponding1819/// From a given object's index and the index of the segment, returns the corresponding
1821/// index of the segment within the final data section. When the segment does not yet1820/// index of the segment within the final data section. When the segment does not yet
1822/// exist, a new one will be initialized and appended. The new index will be returned in that case.1821/// 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 {1822pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, relocatable_index: u32) !?u32 {
1824 const object: Object = self.objects.items[object_index];1823 const object: Object = wasm.objects.items[object_index];
1825 const relocatable_data = object.relocatable_data[relocatable_index];1824 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
1828 switch (relocatable_data.type) {1827 switch (relocatable_data.type) {
1829 .data => {1828 .data => {
1830 const segment_info = object.segment_info[relocatable_data.index];1829 const segment_info = object.segment_info[relocatable_data.index];
1831 const merge_segment = self.base.options.output_mode != .Obj;1830 const merge_segment = wasm.base.options.output_mode != .Obj;
1832 const result = try self.data_segments.getOrPut(self.base.allocator, segment_info.outputName(merge_segment));1831 const result = try wasm.data_segments.getOrPut(wasm.base.allocator, segment_info.outputName(merge_segment));
1833 if (!result.found_existing) {1832 if (!result.found_existing) {
1834 result.value_ptr.* = index;1833 result.value_ptr.* = index;
1835 try self.appendDummySegment();1834 try wasm.appendDummySegment();
1836 return index;1835 return index;
1837 } else return result.value_ptr.*;1836 } else return result.value_ptr.*;
1838 },1837 },
1839 .code => return self.code_section_index orelse blk: {1838 .code => return wasm.code_section_index orelse blk: {
1840 self.code_section_index = index;1839 wasm.code_section_index = index;
1841 try self.appendDummySegment();1840 try wasm.appendDummySegment();
1842 break :blk index;1841 break :blk index;
1843 },1842 },
1844 .debug => {1843 .debug => {
1845 const debug_name = object.getDebugName(relocatable_data);1844 const debug_name = object.getDebugName(relocatable_data);
1846 if (mem.eql(u8, debug_name, ".debug_info")) {1845 if (mem.eql(u8, debug_name, ".debug_info")) {
1847 return self.debug_info_index orelse blk: {1846 return wasm.debug_info_index orelse blk: {
1848 self.debug_info_index = index;1847 wasm.debug_info_index = index;
1849 try self.appendDummySegment();1848 try wasm.appendDummySegment();
1850 break :blk index;1849 break :blk index;
1851 };1850 };
1852 } else if (mem.eql(u8, debug_name, ".debug_line")) {1851 } else if (mem.eql(u8, debug_name, ".debug_line")) {
1853 return self.debug_line_index orelse blk: {1852 return wasm.debug_line_index orelse blk: {
1854 self.debug_line_index = index;1853 wasm.debug_line_index = index;
1855 try self.appendDummySegment();1854 try wasm.appendDummySegment();
1856 break :blk index;1855 break :blk index;
1857 };1856 };
1858 } else if (mem.eql(u8, debug_name, ".debug_loc")) {1857 } else if (mem.eql(u8, debug_name, ".debug_loc")) {
1859 return self.debug_loc_index orelse blk: {1858 return wasm.debug_loc_index orelse blk: {
1860 self.debug_loc_index = index;1859 wasm.debug_loc_index = index;
1861 try self.appendDummySegment();1860 try wasm.appendDummySegment();
1862 break :blk index;1861 break :blk index;
1863 };1862 };
1864 } else if (mem.eql(u8, debug_name, ".debug_ranges")) {1863 } else if (mem.eql(u8, debug_name, ".debug_ranges")) {
1865 return self.debug_line_index orelse blk: {1864 return wasm.debug_line_index orelse blk: {
1866 self.debug_ranges_index = index;1865 wasm.debug_ranges_index = index;
1867 try self.appendDummySegment();1866 try wasm.appendDummySegment();
1868 break :blk index;1867 break :blk index;
1869 };1868 };
1870 } else if (mem.eql(u8, debug_name, ".debug_pubnames")) {1869 } else if (mem.eql(u8, debug_name, ".debug_pubnames")) {
1871 return self.debug_pubnames_index orelse blk: {1870 return wasm.debug_pubnames_index orelse blk: {
1872 self.debug_pubnames_index = index;1871 wasm.debug_pubnames_index = index;
1873 try self.appendDummySegment();1872 try wasm.appendDummySegment();
1874 break :blk index;1873 break :blk index;
1875 };1874 };
1876 } else if (mem.eql(u8, debug_name, ".debug_pubtypes")) {1875 } else if (mem.eql(u8, debug_name, ".debug_pubtypes")) {
1877 return self.debug_pubtypes_index orelse blk: {1876 return wasm.debug_pubtypes_index orelse blk: {
1878 self.debug_pubtypes_index = index;1877 wasm.debug_pubtypes_index = index;
1879 try self.appendDummySegment();1878 try wasm.appendDummySegment();
1880 break :blk index;1879 break :blk index;
1881 };1880 };
1882 } else if (mem.eql(u8, debug_name, ".debug_abbrev")) {1881 } else if (mem.eql(u8, debug_name, ".debug_abbrev")) {
1883 return self.debug_abbrev_index orelse blk: {1882 return wasm.debug_abbrev_index orelse blk: {
1884 self.debug_abbrev_index = index;1883 wasm.debug_abbrev_index = index;
1885 try self.appendDummySegment();1884 try wasm.appendDummySegment();
1886 break :blk index;1885 break :blk index;
1887 };1886 };
1888 } else if (mem.eql(u8, debug_name, ".debug_str")) {1887 } else if (mem.eql(u8, debug_name, ".debug_str")) {
1889 return self.debug_str_index orelse blk: {1888 return wasm.debug_str_index orelse blk: {
1890 self.debug_str_index = index;1889 wasm.debug_str_index = index;
1891 try self.appendDummySegment();1890 try wasm.appendDummySegment();
1892 break :blk index;1891 break :blk index;
1893 };1892 };
1894 } else {1893 } else {
...@@ -1901,8 +1900,8 @@ pub fn getMatchingSegment(self: *Wasm, object_index: u16, relocatable_index: u32...@@ -1901,8 +1900,8 @@ pub fn getMatchingSegment(self: *Wasm, object_index: u16, relocatable_index: u32
1901}1900}
19021901
1903/// Appends a new segment with default field values1902/// Appends a new segment with default field values
1904fn appendDummySegment(self: *Wasm) !void {1903fn appendDummySegment(wasm: *Wasm) !void {
1905 try self.segments.append(self.base.allocator, .{1904 try wasm.segments.append(wasm.base.allocator, .{
1906 .alignment = 1,1905 .alignment = 1,
1907 .size = 0,1906 .size = 0,
1908 .offset = 0,1907 .offset = 0,
...@@ -1912,8 +1911,8 @@ fn appendDummySegment(self: *Wasm) !void {...@@ -1912,8 +1911,8 @@ fn appendDummySegment(self: *Wasm) !void {
1912/// Returns the symbol index of the error name table.1911/// Returns the symbol index of the error name table.
1913///1912///
1914/// When the symbol does not yet exist, it will create a new one instead.1913/// When the symbol does not yet exist, it will create a new one instead.
1915pub fn getErrorTableSymbol(self: *Wasm) !u32 {1914pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {
1916 if (self.error_table_symbol) |symbol| {1915 if (wasm.error_table_symbol) |symbol| {
1917 return symbol;1916 return symbol;
1918 }1917 }
19191918
...@@ -1922,14 +1921,14 @@ pub fn getErrorTableSymbol(self: *Wasm) !u32 {...@@ -1922,14 +1921,14 @@ pub fn getErrorTableSymbol(self: *Wasm) !u32 {
1922 // during `flush` when we know all possible error names.1921 // during `flush` when we know all possible error names.
19231922
1924 // As sym_index '0' is reserved, we use it for our stack pointer symbol1923 // 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: {1924 const symbol_index = wasm.symbols_free_list.popOrNull() orelse blk: {
1926 const index = @intCast(u32, self.symbols.items.len);1925 const index = @intCast(u32, wasm.symbols.items.len);
1927 _ = try self.symbols.addOne(self.base.allocator);1926 _ = try wasm.symbols.addOne(wasm.base.allocator);
1928 break :blk index;1927 break :blk index;
1929 };1928 };
19301929
1931 const sym_name = try self.string_table.put(self.base.allocator, "__zig_err_name_table");1930 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_name_table");
1932 const symbol = &self.symbols.items[symbol_index];1931 const symbol = &wasm.symbols.items[symbol_index];
1933 symbol.* = .{1932 symbol.* = .{
1934 .name = sym_name,1933 .name = sym_name,
1935 .tag = .data,1934 .tag = .data,
...@@ -1940,17 +1939,17 @@ pub fn getErrorTableSymbol(self: *Wasm) !u32 {...@@ -1940,17 +1939,17 @@ pub fn getErrorTableSymbol(self: *Wasm) !u32 {
19401939
1941 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);1940 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);
1944 atom.* = Atom.empty;1943 atom.* = Atom.empty;
1945 atom.sym_index = symbol_index;1944 atom.sym_index = symbol_index;
1946 atom.alignment = slice_ty.abiAlignment(self.base.options.target);1945 atom.alignment = slice_ty.abiAlignment(wasm.base.options.target);
1947 try self.managed_atoms.append(self.base.allocator, atom);1946 try wasm.managed_atoms.append(wasm.base.allocator, atom);
1948 const loc = atom.symbolLoc();1947 const loc = atom.symbolLoc();
1949 try self.resolved_symbols.put(self.base.allocator, loc, {});1948 try wasm.resolved_symbols.put(wasm.base.allocator, loc, {});
1950 try self.symbol_atom.put(self.base.allocator, loc, atom);1949 try wasm.symbol_atom.put(wasm.base.allocator, loc, atom);
19511950
1952 log.debug("Error name table was created with symbol index: ({d})", .{symbol_index});1951 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;
1954 return symbol_index;1953 return symbol_index;
1955}1954}
19561955
...@@ -1958,24 +1957,24 @@ pub fn getErrorTableSymbol(self: *Wasm) !u32 {...@@ -1958,24 +1957,24 @@ pub fn getErrorTableSymbol(self: *Wasm) !u32 {
1958///1957///
1959/// This creates a table that consists of pointers and length to each error name.1958/// This creates a table that consists of pointers and length to each error name.
1960/// The table is what is being pointed to within the runtime bodies that are generated.1959/// The table is what is being pointed to within the runtime bodies that are generated.
1961fn populateErrorNameTable(self: *Wasm) !void {1960fn populateErrorNameTable(wasm: *Wasm) !void {
1962 const symbol_index = self.error_table_symbol orelse return;1961 const symbol_index = wasm.error_table_symbol orelse return;
1963 const atom: *Atom = self.symbol_atom.get(.{ .file = null, .index = symbol_index }).?;1962 const atom: *Atom = wasm.symbol_atom.get(.{ .file = null, .index = symbol_index }).?;
1964 // Rather than creating a symbol for each individual error name,1963 // Rather than creating a symbol for each individual error name,
1965 // we create a symbol for the entire region of error names. We then calculate1964 // we create a symbol for the entire region of error names. We then calculate
1966 // the pointers into the list using addends which are appended to the relocation.1965 // 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);
1968 names_atom.* = Atom.empty;1967 names_atom.* = Atom.empty;
1969 try self.managed_atoms.append(self.base.allocator, names_atom);1968 try wasm.managed_atoms.append(wasm.base.allocator, names_atom);
1970 const names_symbol_index = self.symbols_free_list.popOrNull() orelse blk: {1969 const names_symbol_index = wasm.symbols_free_list.popOrNull() orelse blk: {
1971 const index = @intCast(u32, self.symbols.items.len);1970 const index = @intCast(u32, wasm.symbols.items.len);
1972 _ = try self.symbols.addOne(self.base.allocator);1971 _ = try wasm.symbols.addOne(wasm.base.allocator);
1973 break :blk index;1972 break :blk index;
1974 };1973 };
1975 names_atom.sym_index = names_symbol_index;1974 names_atom.sym_index = names_symbol_index;
1976 names_atom.alignment = 1;1975 names_atom.alignment = 1;
1977 const sym_name = try self.string_table.put(self.base.allocator, "__zig_err_names");1976 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_names");
1978 const names_symbol = &self.symbols.items[names_symbol_index];1977 const names_symbol = &wasm.symbols.items[names_symbol_index];
1979 names_symbol.* = .{1978 names_symbol.* = .{
1980 .name = sym_name,1979 .name = sym_name,
1981 .tag = .data,1980 .tag = .data,
...@@ -1988,27 +1987,27 @@ fn populateErrorNameTable(self: *Wasm) !void {...@@ -1988,27 +1987,27 @@ fn populateErrorNameTable(self: *Wasm) !void {
19881987
1989 // Addend for each relocation to the table1988 // Addend for each relocation to the table
1990 var addend: u32 = 0;1989 var addend: u32 = 0;
1991 const mod = self.base.options.module.?;1990 const mod = wasm.base.options.module.?;
1992 for (mod.error_name_list.items) |error_name| {1991 for (mod.error_name_list.items) |error_name| {
1993 const len = @intCast(u32, error_name.len + 1); // names are 0-termianted1992 const len = @intCast(u32, error_name.len + 1); // names are 0-termianted
19941993
1995 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);1994 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
1996 const offset = @intCast(u32, atom.code.items.len);1995 const offset = @intCast(u32, atom.code.items.len);
1997 // first we create the data for the slice of the name1996 // 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 relocated1997 try atom.code.appendNTimes(wasm.base.allocator, 0, 4); // ptr to name, will be relocated
1999 try atom.code.writer(self.base.allocator).writeIntLittle(u32, len - 1);1998 try atom.code.writer(wasm.base.allocator).writeIntLittle(u32, len - 1);
2000 // create relocation to the error name1999 // create relocation to the error name
2001 try atom.relocs.append(self.base.allocator, .{2000 try atom.relocs.append(wasm.base.allocator, .{
2002 .index = names_symbol_index,2001 .index = names_symbol_index,
2003 .relocation_type = .R_WASM_MEMORY_ADDR_I32,2002 .relocation_type = .R_WASM_MEMORY_ADDR_I32,
2004 .offset = offset,2003 .offset = offset,
2005 .addend = addend,2004 .addend = addend,
2006 });2005 });
2007 atom.size += @intCast(u32, slice_ty.abiSize(self.base.options.target));2006 atom.size += @intCast(u32, slice_ty.abiSize(wasm.base.options.target));
2008 addend += len;2007 addend += len;
20092008
2010 // as we updated the error name table, we now store the actual name within the names atom2009 // 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);
2012 names_atom.code.appendSliceAssumeCapacity(error_name);2011 names_atom.code.appendSliceAssumeCapacity(error_name);
2013 names_atom.code.appendAssumeCapacity(0);2012 names_atom.code.appendAssumeCapacity(0);
20142013
...@@ -2017,51 +2016,51 @@ fn populateErrorNameTable(self: *Wasm) !void {...@@ -2017,51 +2016,51 @@ fn populateErrorNameTable(self: *Wasm) !void {
2017 names_atom.size = addend;2016 names_atom.size = addend;
20182017
2019 const name_loc = names_atom.symbolLoc();2018 const name_loc = names_atom.symbolLoc();
2020 try self.resolved_symbols.put(self.base.allocator, name_loc, {});2019 try wasm.resolved_symbols.put(wasm.base.allocator, name_loc, {});
2021 try self.symbol_atom.put(self.base.allocator, name_loc, names_atom);2020 try wasm.symbol_atom.put(wasm.base.allocator, name_loc, names_atom);
20222021
2023 // link the atoms with the rest of the binary so they can be allocated2022 // link the atoms with the rest of the binary so they can be allocated
2024 // and relocations will be performed.2023 // and relocations will be performed.
2025 try self.parseAtom(atom, .{ .data = .read_only });2024 try wasm.parseAtom(atom, .{ .data = .read_only });
2026 try self.parseAtom(names_atom, .{ .data = .read_only });2025 try wasm.parseAtom(names_atom, .{ .data = .read_only });
2027}2026}
20282027
2029/// From a given index variable, creates a new debug section.2028/// From a given index variable, creates a new debug section.
2030/// This initializes the index, appends a new segment,2029/// This initializes the index, appends a new segment,
2031/// and finally, creates a managed `Atom`.2030/// and finally, creates a managed `Atom`.
2032pub fn createDebugSectionForIndex(self: *Wasm, index: *?u32, name: []const u8) !*Atom {2031pub fn createDebugSectionForIndex(wasm: *Wasm, index: *?u32, name: []const u8) !*Atom {
2033 const new_index = @intCast(u32, self.segments.items.len);2032 const new_index = @intCast(u32, wasm.segments.items.len);
2034 index.* = new_index;2033 index.* = new_index;
2035 try self.appendDummySegment();2034 try wasm.appendDummySegment();
2036 // _ = index;2035 // _ = index;
20372036
2038 const sym_index = self.symbols_free_list.popOrNull() orelse idx: {2037 const sym_index = wasm.symbols_free_list.popOrNull() orelse idx: {
2039 const tmp_index = @intCast(u32, self.symbols.items.len);2038 const tmp_index = @intCast(u32, wasm.symbols.items.len);
2040 _ = try self.symbols.addOne(self.base.allocator);2039 _ = try wasm.symbols.addOne(wasm.base.allocator);
2041 break :idx tmp_index;2040 break :idx tmp_index;
2042 };2041 };
2043 self.symbols.items[sym_index] = .{2042 wasm.symbols.items[sym_index] = .{
2044 .tag = .section,2043 .tag = .section,
2045 .name = try self.string_table.put(self.base.allocator, name),2044 .name = try wasm.string_table.put(wasm.base.allocator, name),
2046 .index = 0,2045 .index = 0,
2047 .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL),2046 .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
2048 };2047 };
20492048
2050 const atom = try self.base.allocator.create(Atom);2049 const atom = try wasm.base.allocator.create(Atom);
2051 atom.* = Atom.empty;2050 atom.* = Atom.empty;
2052 atom.alignment = 1; // debug sections are always 1-byte-aligned2051 atom.alignment = 1; // debug sections are always 1-byte-aligned
2053 atom.sym_index = sym_index;2052 atom.sym_index = sym_index;
2054 try self.managed_atoms.append(self.base.allocator, atom);2053 try wasm.managed_atoms.append(wasm.base.allocator, atom);
2055 try self.symbol_atom.put(self.base.allocator, atom.symbolLoc(), atom);2054 try wasm.symbol_atom.put(wasm.base.allocator, atom.symbolLoc(), atom);
2056 return atom;2055 return atom;
2057}2056}
20582057
2059fn resetState(self: *Wasm) void {2058fn resetState(wasm: *Wasm) void {
2060 for (self.segment_info.values()) |segment_info| {2059 for (wasm.segment_info.values()) |segment_info| {
2061 self.base.allocator.free(segment_info.name);2060 wasm.base.allocator.free(segment_info.name);
2062 }2061 }
2063 if (self.base.options.module) |mod| {2062 if (wasm.base.options.module) |mod| {
2064 var decl_it = self.decls.keyIterator();2063 var decl_it = wasm.decls.keyIterator();
2065 while (decl_it.next()) |decl_index_ptr| {2064 while (decl_it.next()) |decl_index_ptr| {
2066 const decl = mod.declPtr(decl_index_ptr.*);2065 const decl = mod.declPtr(decl_index_ptr.*);
2067 const atom = &decl.link.wasm;2066 const atom = &decl.link.wasm;
...@@ -2074,46 +2073,46 @@ fn resetState(self: *Wasm) void {...@@ -2074,46 +2073,46 @@ fn resetState(self: *Wasm) void {
2074 }2073 }
2075 }2074 }
2076 }2075 }
2077 self.functions.clearRetainingCapacity();2076 wasm.functions.clearRetainingCapacity();
2078 self.exports.clearRetainingCapacity();2077 wasm.exports.clearRetainingCapacity();
2079 self.segments.clearRetainingCapacity();2078 wasm.segments.clearRetainingCapacity();
2080 self.segment_info.clearRetainingCapacity();2079 wasm.segment_info.clearRetainingCapacity();
2081 self.data_segments.clearRetainingCapacity();2080 wasm.data_segments.clearRetainingCapacity();
2082 self.atoms.clearRetainingCapacity();2081 wasm.atoms.clearRetainingCapacity();
2083 self.symbol_atom.clearRetainingCapacity();2082 wasm.symbol_atom.clearRetainingCapacity();
2084 self.code_section_index = null;2083 wasm.code_section_index = null;
2085 self.debug_info_index = null;2084 wasm.debug_info_index = null;
2086 self.debug_line_index = null;2085 wasm.debug_line_index = null;
2087 self.debug_loc_index = null;2086 wasm.debug_loc_index = null;
2088 self.debug_str_index = null;2087 wasm.debug_str_index = null;
2089 self.debug_ranges_index = null;2088 wasm.debug_ranges_index = null;
2090 self.debug_abbrev_index = null;2089 wasm.debug_abbrev_index = null;
2091 self.debug_pubnames_index = null;2090 wasm.debug_pubnames_index = null;
2092 self.debug_pubtypes_index = null;2091 wasm.debug_pubtypes_index = null;
2093}2092}
20942093
2095pub fn flush(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {2094pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
2096 if (self.base.options.emit == null) {2095 if (wasm.base.options.emit == null) {
2097 if (build_options.have_llvm) {2096 if (build_options.have_llvm) {
2098 if (self.llvm_object) |llvm_object| {2097 if (wasm.llvm_object) |llvm_object| {
2099 return try llvm_object.flushModule(comp, prog_node);2098 return try llvm_object.flushModule(comp, prog_node);
2100 }2099 }
2101 }2100 }
2102 return;2101 return;
2103 }2102 }
2104 if (build_options.have_llvm and self.base.options.use_lld) {2103 if (build_options.have_llvm and wasm.base.options.use_lld) {
2105 return self.linkWithLLD(comp, prog_node);2104 return wasm.linkWithLLD(comp, prog_node);
2106 } else {2105 } else {
2107 return self.flushModule(comp, prog_node);2106 return wasm.flushModule(comp, prog_node);
2108 }2107 }
2109}2108}
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 {
2112 const tracy = trace(@src());2111 const tracy = trace(@src());
2113 defer tracy.end();2112 defer tracy.end();
21142113
2115 if (build_options.have_llvm) {2114 if (build_options.have_llvm) {
2116 if (self.llvm_object) |llvm_object| {2115 if (wasm.llvm_object) |llvm_object| {
2117 return try llvm_object.flushModule(comp, prog_node);2116 return try llvm_object.flushModule(comp, prog_node);
2118 }2117 }
2119 }2118 }
...@@ -2123,7 +2122,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2123,7 +2122,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2123 defer sub_prog_node.end();2122 defer sub_prog_node.end();
21242123
2125 // ensure the error names table is populated when an error name is referenced2124 // ensure the error names table is populated when an error name is referenced
2126 try self.populateErrorNameTable();2125 try wasm.populateErrorNameTable();
21272126
2128 // The amount of sections that will be written2127 // The amount of sections that will be written
2129 var section_count: u32 = 0;2128 var section_count: u32 = 0;
...@@ -2133,15 +2132,15 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2133,15 +2132,15 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2133 var data_section_index: ?u32 = null;2132 var data_section_index: ?u32 = null;
21342133
2135 // Used for all temporary memory allocated during flushin2134 // 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);
2137 defer arena_instance.deinit();2136 defer arena_instance.deinit();
2138 const arena = arena_instance.allocator();2137 const arena = arena_instance.allocator();
21392138
2140 // Positional arguments to the linker such as object files and static archives.2139 // Positional arguments to the linker such as object files and static archives.
2141 var positionals = std.ArrayList([]const u8).init(arena);2140 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| {
2145 positionals.appendAssumeCapacity(object.path);2144 positionals.appendAssumeCapacity(object.path);
2146 }2145 }
21472146
...@@ -2153,66 +2152,66 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2153,66 +2152,66 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2153 try positionals.append(lib.full_object_path);2152 try positionals.append(lib.full_object_path);
2154 }2153 }
21552154
2156 try self.parseInputFiles(positionals.items);2155 try wasm.parseInputFiles(positionals.items);
21572156
2158 for (self.objects.items) |_, object_index| {2157 for (wasm.objects.items) |_, object_index| {
2159 try self.resolveSymbolsInObject(@intCast(u16, object_index));2158 try wasm.resolveSymbolsInObject(@intCast(u16, object_index));
2160 }2159 }
21612160
2162 try self.resolveSymbolsInArchives();2161 try wasm.resolveSymbolsInArchives();
2163 try self.checkUndefinedSymbols();2162 try wasm.checkUndefinedSymbols();
21642163
2165 // When we finish/error we reset the state of the linker2164 // When we finish/error we reset the state of the linker
2166 // So we can rebuild the binary file on each incremental update2165 // So we can rebuild the binary file on each incremental update
2167 defer self.resetState();2166 defer wasm.resetState();
2168 try self.setupStart();2167 try wasm.setupStart();
2169 try self.setupImports();2168 try wasm.setupImports();
2170 if (self.base.options.module) |mod| {2169 if (wasm.base.options.module) |mod| {
2171 var decl_it = self.decls.keyIterator();2170 var decl_it = wasm.decls.keyIterator();
2172 while (decl_it.next()) |decl_index_ptr| {2171 while (decl_it.next()) |decl_index_ptr| {
2173 const decl = mod.declPtr(decl_index_ptr.*);2172 const decl = mod.declPtr(decl_index_ptr.*);
2174 if (decl.isExtern()) continue;2173 if (decl.isExtern()) continue;
2175 const atom = &decl.*.link.wasm;2174 const atom = &decl.*.link.wasm;
2176 if (decl.ty.zigTypeTag() == .Fn) {2175 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 });
2178 } else if (decl.getVariable()) |variable| {2177 } else if (decl.getVariable()) |variable| {
2179 if (!variable.is_mutable) {2178 if (!variable.is_mutable) {
2180 try self.parseAtom(atom, .{ .data = .read_only });2179 try wasm.parseAtom(atom, .{ .data = .read_only });
2181 } else if (variable.init.isUndefDeep()) {2180 } else if (variable.init.isUndefDeep()) {
2182 try self.parseAtom(atom, .{ .data = .uninitialized });2181 try wasm.parseAtom(atom, .{ .data = .uninitialized });
2183 } else {2182 } else {
2184 try self.parseAtom(atom, .{ .data = .initialized });2183 try wasm.parseAtom(atom, .{ .data = .initialized });
2185 }2184 }
2186 } else {2185 } else {
2187 try self.parseAtom(atom, .{ .data = .read_only });2186 try wasm.parseAtom(atom, .{ .data = .read_only });
2188 }2187 }
21892188
2190 // also parse atoms for a decl's locals2189 // also parse atoms for a decl's locals
2191 for (atom.locals.items) |*local_atom| {2190 for (atom.locals.items) |*local_atom| {
2192 try self.parseAtom(local_atom, .{ .data = .read_only });2191 try wasm.parseAtom(local_atom, .{ .data = .read_only });
2193 }2192 }
2194 }2193 }
21952194
2196 if (self.dwarf) |*dwarf| {2195 if (wasm.dwarf) |*dwarf| {
2197 try dwarf.flushModule(&self.base, self.base.options.module.?);2196 try dwarf.flushModule(&wasm.base, wasm.base.options.module.?);
2198 }2197 }
2199 }2198 }
22002199
2201 for (self.objects.items) |*object, object_index| {2200 for (wasm.objects.items) |*object, object_index| {
2202 try object.parseIntoAtoms(self.base.allocator, @intCast(u16, object_index), self);2201 try object.parseIntoAtoms(wasm.base.allocator, @intCast(u16, object_index), wasm);
2203 }2202 }
22042203
2205 try self.allocateAtoms();2204 try wasm.allocateAtoms();
2206 try self.setupMemory();2205 try wasm.setupMemory();
2207 self.mapFunctionTable();2206 wasm.mapFunctionTable();
2208 try self.mergeSections();2207 try wasm.mergeSections();
2209 try self.mergeTypes();2208 try wasm.mergeTypes();
2210 try self.setupExports();2209 try wasm.setupExports();
22112210
2212 const header_size = 5 + 1;2211 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);
2216 defer binary_bytes.deinit();2215 defer binary_bytes.deinit();
2217 const binary_writer = binary_bytes.writer();2216 const binary_writer = binary_bytes.writer();
22182217
...@@ -2221,18 +2220,18 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2221,18 +2220,18 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2221 try binary_writer.writeAll(&[_]u8{0} ** 8);2220 try binary_writer.writeAll(&[_]u8{0} ** 8);
22222221
2223 // Type section2222 // Type section
2224 if (self.func_types.items.len != 0) {2223 if (wasm.func_types.items.len != 0) {
2225 const header_offset = try reserveVecSectionHeader(&binary_bytes);2224 const header_offset = try reserveVecSectionHeader(&binary_bytes);
2226 log.debug("Writing type section. Count: ({d})", .{self.func_types.items.len});2225 log.debug("Writing type section. Count: ({d})", .{wasm.func_types.items.len});
2227 for (self.func_types.items) |func_type| {2226 for (wasm.func_types.items) |func_type| {
2228 try leb.writeULEB128(binary_writer, wasm.function_type);2227 try leb.writeULEB128(binary_writer, std.wasm.function_type);
2229 try leb.writeULEB128(binary_writer, @intCast(u32, func_type.params.len));2228 try leb.writeULEB128(binary_writer, @intCast(u32, func_type.params.len));
2230 for (func_type.params) |param_ty| {2229 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));
2232 }2231 }
2233 try leb.writeULEB128(binary_writer, @intCast(u32, func_type.returns.len));2232 try leb.writeULEB128(binary_writer, @intCast(u32, func_type.returns.len));
2234 for (func_type.returns) |ret_ty| {2233 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));
2236 }2235 }
2237 }2236 }
22382237
...@@ -2241,50 +2240,50 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2241,50 +2240,50 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2241 header_offset,2240 header_offset,
2242 .type,2241 .type,
2243 @intCast(u32, binary_bytes.items.len - header_offset - header_size),2242 @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),
2245 );2244 );
2246 section_count += 1;2245 section_count += 1;
2247 }2246 }
22482247
2249 // Import section2248 // Import section
2250 const import_memory = self.base.options.import_memory or is_obj;2249 const import_memory = wasm.base.options.import_memory or is_obj;
2251 const import_table = self.base.options.import_table or is_obj;2250 const import_table = wasm.base.options.import_table or is_obj;
2252 if (self.imports.count() != 0 or import_memory or import_table) {2251 if (wasm.imports.count() != 0 or import_memory or import_table) {
2253 const header_offset = try reserveVecSectionHeader(&binary_bytes);2252 const header_offset = try reserveVecSectionHeader(&binary_bytes);
22542253
2255 // import table is always first table so emit that first2254 // import table is always first table so emit that first
2256 if (import_table) {2255 if (import_table) {
2257 const table_imp: types.Import = .{2256 const table_imp: types.Import = .{
2258 .module_name = try self.string_table.put(self.base.allocator, self.host_name),2257 .module_name = try wasm.string_table.put(wasm.base.allocator, wasm.host_name),
2259 .name = try self.string_table.put(self.base.allocator, "__indirect_function_table"),2258 .name = try wasm.string_table.put(wasm.base.allocator, "__indirect_function_table"),
2260 .kind = .{2259 .kind = .{
2261 .table = .{2260 .table = .{
2262 .limits = .{2261 .limits = .{
2263 .min = @intCast(u32, self.function_table.count()),2262 .min = @intCast(u32, wasm.function_table.count()),
2264 .max = null,2263 .max = null,
2265 },2264 },
2266 .reftype = .funcref,2265 .reftype = .funcref,
2267 },2266 },
2268 },2267 },
2269 };2268 };
2270 try self.emitImport(binary_writer, table_imp);2269 try wasm.emitImport(binary_writer, table_imp);
2271 }2270 }
22722271
2273 var it = self.imports.iterator();2272 var it = wasm.imports.iterator();
2274 while (it.next()) |entry| {2273 while (it.next()) |entry| {
2275 assert(entry.key_ptr.*.getSymbol(self).isUndefined());2274 assert(entry.key_ptr.*.getSymbol(wasm).isUndefined());
2276 const import = entry.value_ptr.*;2275 const import = entry.value_ptr.*;
2277 try self.emitImport(binary_writer, import);2276 try wasm.emitImport(binary_writer, import);
2278 }2277 }
22792278
2280 if (import_memory) {2279 if (import_memory) {
2281 const mem_name = if (is_obj) "__linear_memory" else "memory";2280 const mem_name = if (is_obj) "__linear_memory" else "memory";
2282 const mem_imp: types.Import = .{2281 const mem_imp: types.Import = .{
2283 .module_name = try self.string_table.put(self.base.allocator, self.host_name),2282 .module_name = try wasm.string_table.put(wasm.base.allocator, wasm.host_name),
2284 .name = try self.string_table.put(self.base.allocator, mem_name),2283 .name = try wasm.string_table.put(wasm.base.allocator, mem_name),
2285 .kind = .{ .memory = self.memories.limits },2284 .kind = .{ .memory = wasm.memories.limits },
2286 };2285 };
2287 try self.emitImport(binary_writer, mem_imp);2286 try wasm.emitImport(binary_writer, mem_imp);
2288 }2287 }
22892288
2290 try writeVecSectionHeader(2289 try writeVecSectionHeader(
...@@ -2292,15 +2291,15 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2292,15 +2291,15 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2292 header_offset,2291 header_offset,
2293 .import,2292 .import,
2294 @intCast(u32, binary_bytes.items.len - header_offset - header_size),2293 @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)),
2296 );2295 );
2297 section_count += 1;2296 section_count += 1;
2298 }2297 }
22992298
2300 // Function section2299 // Function section
2301 if (self.functions.count() != 0) {2300 if (wasm.functions.count() != 0) {
2302 const header_offset = try reserveVecSectionHeader(&binary_bytes);2301 const header_offset = try reserveVecSectionHeader(&binary_bytes);
2303 for (self.functions.values()) |function| {2302 for (wasm.functions.values()) |function| {
2304 try leb.writeULEB128(binary_writer, function.type_index);2303 try leb.writeULEB128(binary_writer, function.type_index);
2305 }2304 }
23062305
...@@ -2309,19 +2308,19 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2309,19 +2308,19 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2309 header_offset,2308 header_offset,
2310 .function,2309 .function,
2311 @intCast(u32, binary_bytes.items.len - header_offset - header_size),2310 @intCast(u32, binary_bytes.items.len - header_offset - header_size),
2312 @intCast(u32, self.functions.count()),2311 @intCast(u32, wasm.functions.count()),
2313 );2312 );
2314 section_count += 1;2313 section_count += 1;
2315 }2314 }
23162315
2317 // Table section2316 // Table section
2318 const export_table = self.base.options.export_table;2317 const export_table = wasm.base.options.export_table;
2319 if (!import_table and self.function_table.count() != 0) {2318 if (!import_table and wasm.function_table.count() != 0) {
2320 const header_offset = try reserveVecSectionHeader(&binary_bytes);2319 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));
2323 try emitLimits(binary_writer, .{2322 try emitLimits(binary_writer, .{
2324 .min = @intCast(u32, self.function_table.count()) + 1,2323 .min = @intCast(u32, wasm.function_table.count()) + 1,
2325 .max = null,2324 .max = null,
2326 });2325 });
23272326
...@@ -2339,7 +2338,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2339,7 +2338,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2339 if (!import_memory) {2338 if (!import_memory) {
2340 const header_offset = try reserveVecSectionHeader(&binary_bytes);2339 const header_offset = try reserveVecSectionHeader(&binary_bytes);
23412340
2342 try emitLimits(binary_writer, self.memories.limits);2341 try emitLimits(binary_writer, wasm.memories.limits);
2343 try writeVecSectionHeader(2342 try writeVecSectionHeader(
2344 binary_bytes.items,2343 binary_bytes.items,
2345 header_offset,2344 header_offset,
...@@ -2351,11 +2350,11 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2351,11 +2350,11 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2351 }2350 }
23522351
2353 // Global section (used to emit stack pointer)2352 // Global section (used to emit stack pointer)
2354 if (self.wasm_globals.items.len > 0) {2353 if (wasm.wasm_globals.items.len > 0) {
2355 const header_offset = try reserveVecSectionHeader(&binary_bytes);2354 const header_offset = try reserveVecSectionHeader(&binary_bytes);
23562355
2357 for (self.wasm_globals.items) |global| {2356 for (wasm.wasm_globals.items) |global| {
2358 try binary_writer.writeByte(wasm.valtype(global.global_type.valtype));2357 try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype));
2359 try binary_writer.writeByte(@boolToInt(global.global_type.mutable));2358 try binary_writer.writeByte(@boolToInt(global.global_type.mutable));
2360 try emitInit(binary_writer, global.init);2359 try emitInit(binary_writer, global.init);
2361 }2360 }
...@@ -2365,17 +2364,17 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2365,17 +2364,17 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2365 header_offset,2364 header_offset,
2366 .global,2365 .global,
2367 @intCast(u32, binary_bytes.items.len - header_offset - header_size),2366 @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),
2369 );2368 );
2370 section_count += 1;2369 section_count += 1;
2371 }2370 }
23722371
2373 // Export section2372 // 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) {
2375 const header_offset = try reserveVecSectionHeader(&binary_bytes);2374 const header_offset = try reserveVecSectionHeader(&binary_bytes);
23762375
2377 for (self.exports.items) |exp| {2376 for (wasm.exports.items) |exp| {
2378 const name = self.string_table.get(exp.name);2377 const name = wasm.string_table.get(exp.name);
2379 try leb.writeULEB128(binary_writer, @intCast(u32, name.len));2378 try leb.writeULEB128(binary_writer, @intCast(u32, name.len));
2380 try binary_writer.writeAll(name);2379 try binary_writer.writeAll(name);
2381 try leb.writeULEB128(binary_writer, @enumToInt(exp.kind));2380 try leb.writeULEB128(binary_writer, @enumToInt(exp.kind));
...@@ -2385,14 +2384,14 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2385,14 +2384,14 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2385 if (export_table) {2384 if (export_table) {
2386 try leb.writeULEB128(binary_writer, @intCast(u32, "__indirect_function_table".len));2385 try leb.writeULEB128(binary_writer, @intCast(u32, "__indirect_function_table".len));
2387 try binary_writer.writeAll("__indirect_function_table");2386 try binary_writer.writeAll("__indirect_function_table");
2388 try binary_writer.writeByte(wasm.externalKind(.table));2387 try binary_writer.writeByte(std.wasm.externalKind(.table));
2389 try leb.writeULEB128(binary_writer, @as(u32, 0)); // function table is always the first table2388 try leb.writeULEB128(binary_writer, @as(u32, 0)); // function table is always the first table
2390 }2389 }
23912390
2392 if (!import_memory) {2391 if (!import_memory) {
2393 try leb.writeULEB128(binary_writer, @intCast(u32, "memory".len));2392 try leb.writeULEB128(binary_writer, @intCast(u32, "memory".len));
2394 try binary_writer.writeAll("memory");2393 try binary_writer.writeAll("memory");
2395 try binary_writer.writeByte(wasm.externalKind(.memory));2394 try binary_writer.writeByte(std.wasm.externalKind(.memory));
2396 try leb.writeULEB128(binary_writer, @as(u32, 0));2395 try leb.writeULEB128(binary_writer, @as(u32, 0));
2397 }2396 }
23982397
...@@ -2401,13 +2400,13 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2401,13 +2400,13 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2401 header_offset,2400 header_offset,
2402 .@"export",2401 .@"export",
2403 @intCast(u32, binary_bytes.items.len - header_offset - header_size),2402 @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),
2405 );2404 );
2406 section_count += 1;2405 section_count += 1;
2407 }2406 }
24082407
2409 // element section (function table)2408 // element section (function table)
2410 if (self.function_table.count() > 0) {2409 if (wasm.function_table.count() > 0) {
2411 const header_offset = try reserveVecSectionHeader(&binary_bytes);2410 const header_offset = try reserveVecSectionHeader(&binary_bytes);
24122411
2413 var flags: u32 = 0x2; // Yes we have a table2412 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...@@ -2415,10 +2414,10 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2415 try leb.writeULEB128(binary_writer, @as(u32, 0)); // index of that table. TODO: Store synthetic symbols2414 try leb.writeULEB128(binary_writer, @as(u32, 0)); // index of that table. TODO: Store synthetic symbols
2416 try emitInit(binary_writer, .{ .i32_const = 1 }); // We start at index 1, so unresolved function pointers are invalid2415 try emitInit(binary_writer, .{ .i32_const = 1 }); // We start at index 1, so unresolved function pointers are invalid
2417 try leb.writeULEB128(binary_writer, @as(u8, 0));2416 try leb.writeULEB128(binary_writer, @as(u8, 0));
2418 try leb.writeULEB128(binary_writer, @intCast(u32, self.function_table.count()));2417 try leb.writeULEB128(binary_writer, @intCast(u32, wasm.function_table.count()));
2419 var symbol_it = self.function_table.keyIterator();2418 var symbol_it = wasm.function_table.keyIterator();
2420 while (symbol_it.next()) |symbol_loc_ptr| {2419 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);
2422 }2421 }
24232422
2424 try writeVecSectionHeader(2423 try writeVecSectionHeader(
...@@ -2433,17 +2432,17 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2433,17 +2432,17 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
24332432
2434 // Code section2433 // Code section
2435 var code_section_size: u32 = 0;2434 var code_section_size: u32 = 0;
2436 if (self.code_section_index) |code_index| {2435 if (wasm.code_section_index) |code_index| {
2437 const header_offset = try reserveVecSectionHeader(&binary_bytes);2436 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
2440 // The code section must be sorted in line with the function order.2439 // 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());
2442 defer sorted_atoms.deinit();2441 defer sorted_atoms.deinit();
24432442
2444 while (true) {2443 while (true) {
2445 if (!is_obj) {2444 if (!is_obj) {
2446 atom.resolveRelocs(self);2445 atom.resolveRelocs(wasm);
2447 }2446 }
2448 sorted_atoms.appendAssumeCapacity(atom);2447 sorted_atoms.appendAssumeCapacity(atom);
2449 atom = atom.next orelse break;2448 atom = atom.next orelse break;
...@@ -2457,7 +2456,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2457,7 +2456,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2457 }2456 }
2458 }.sort;2457 }.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
2462 for (sorted_atoms.items) |sorted_atom| {2461 for (sorted_atoms.items) |sorted_atom| {
2463 try leb.writeULEB128(binary_writer, sorted_atom.size);2462 try leb.writeULEB128(binary_writer, sorted_atom.size);
...@@ -2470,17 +2469,17 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2470,17 +2469,17 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2470 header_offset,2469 header_offset,
2471 .code,2470 .code,
2472 code_section_size,2471 code_section_size,
2473 @intCast(u32, self.functions.count()),2472 @intCast(u32, wasm.functions.count()),
2474 );2473 );
2475 code_section_index = section_count;2474 code_section_index = section_count;
2476 section_count += 1;2475 section_count += 1;
2477 }2476 }
24782477
2479 // Data section2478 // Data section
2480 if (self.data_segments.count() != 0) {2479 if (wasm.data_segments.count() != 0) {
2481 const header_offset = try reserveVecSectionHeader(&binary_bytes);2480 const header_offset = try reserveVecSectionHeader(&binary_bytes);
24822481
2483 var it = self.data_segments.iterator();2482 var it = wasm.data_segments.iterator();
2484 var segment_count: u32 = 0;2483 var segment_count: u32 = 0;
2485 while (it.next()) |entry| {2484 while (it.next()) |entry| {
2486 // do not output 'bss' section unless we import memory and therefore2485 // 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...@@ -2488,8 +2487,8 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2488 if (!import_memory and std.mem.eql(u8, entry.key_ptr.*, ".bss")) continue;2487 if (!import_memory and std.mem.eql(u8, entry.key_ptr.*, ".bss")) continue;
2489 segment_count += 1;2488 segment_count += 1;
2490 const atom_index = entry.value_ptr.*;2489 const atom_index = entry.value_ptr.*;
2491 var atom: *Atom = self.atoms.getPtr(atom_index).?.*.getFirst();2490 var atom: *Atom = wasm.atoms.getPtr(atom_index).?.*.getFirst();
2492 const segment = self.segments.items[atom_index];2491 const segment = wasm.segments.items[atom_index];
24932492
2494 // flag and index to memory section (currently, there can only be 1 memory section in wasm)2493 // flag and index to memory section (currently, there can only be 1 memory section in wasm)
2495 try leb.writeULEB128(binary_writer, @as(u32, 0));2494 try leb.writeULEB128(binary_writer, @as(u32, 0));
...@@ -2501,7 +2500,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2501,7 +2500,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2501 var current_offset: u32 = 0;2500 var current_offset: u32 = 0;
2502 while (true) {2501 while (true) {
2503 if (!is_obj) {2502 if (!is_obj) {
2504 atom.resolveRelocs(self);2503 atom.resolveRelocs(wasm);
2505 }2504 }
25062505
2507 // Pad with zeroes to ensure all segments are aligned2506 // 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...@@ -2546,25 +2545,25 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2546 // we never store all symbols in a single table, but store a location reference instead.2545 // we never store all symbols in a single table, but store a location reference instead.
2547 // This means that for a relocatable object file, we need to generate one and provide it to the relocation sections.2546 // This means that for a relocatable object file, we need to generate one and provide it to the relocation sections.
2548 var symbol_table = std.AutoArrayHashMap(SymbolLoc, u32).init(arena);2547 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);
2550 if (code_section_index) |code_index| {2549 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);
2552 }2551 }
2553 if (data_section_index) |data_index| {2552 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);
2555 }2554 }
2556 } else if (!self.base.options.strip) {2555 } else if (!wasm.base.options.strip) {
2557 if (self.dwarf) |*dwarf| {2556 if (wasm.dwarf) |*dwarf| {
2558 const mod = self.base.options.module.?;2557 const mod = wasm.base.options.module.?;
2559 try dwarf.writeDbgAbbrev(&self.base);2558 try dwarf.writeDbgAbbrev(&wasm.base);
2560 // for debug info and ranges, the address is always 0,2559 // for debug info and ranges, the address is always 0,
2561 // as locations are always offsets relative to 'code' section.2560 // as locations are always offsets relative to 'code' section.
2562 try dwarf.writeDbgInfoHeader(&self.base, mod, 0, code_section_size);2561 try dwarf.writeDbgInfoHeader(&wasm.base, mod, 0, code_section_size);
2563 try dwarf.writeDbgAranges(&self.base, 0, code_section_size);2562 try dwarf.writeDbgAranges(&wasm.base, 0, code_section_size);
2564 try dwarf.writeDbgLineHeader(&self.base, mod);2563 try dwarf.writeDbgLineHeader(&wasm.base, mod);
2565 }2564 }
25662565
2567 var debug_bytes = std.ArrayList(u8).init(self.base.allocator);2566 var debug_bytes = std.ArrayList(u8).init(wasm.base.allocator);
2568 defer debug_bytes.deinit();2567 defer debug_bytes.deinit();
25692568
2570 const DebugSection = struct {2569 const DebugSection = struct {
...@@ -2573,21 +2572,21 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2573,21 +2572,21 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2573 };2572 };
25742573
2575 const debug_sections: []const DebugSection = &.{2574 const debug_sections: []const DebugSection = &.{
2576 .{ .name = ".debug_info", .index = self.debug_info_index },2575 .{ .name = ".debug_info", .index = wasm.debug_info_index },
2577 .{ .name = ".debug_pubtypes", .index = self.debug_pubtypes_index },2576 .{ .name = ".debug_pubtypes", .index = wasm.debug_pubtypes_index },
2578 .{ .name = ".debug_abbrev", .index = self.debug_abbrev_index },2577 .{ .name = ".debug_abbrev", .index = wasm.debug_abbrev_index },
2579 .{ .name = ".debug_line", .index = self.debug_line_index },2578 .{ .name = ".debug_line", .index = wasm.debug_line_index },
2580 .{ .name = ".debug_str", .index = self.debug_str_index },2579 .{ .name = ".debug_str", .index = wasm.debug_str_index },
2581 .{ .name = ".debug_pubnames", .index = self.debug_pubnames_index },2580 .{ .name = ".debug_pubnames", .index = wasm.debug_pubnames_index },
2582 .{ .name = ".debug_loc", .index = self.debug_loc_index },2581 .{ .name = ".debug_loc", .index = wasm.debug_loc_index },
2583 .{ .name = ".debug_ranges", .index = self.debug_ranges_index },2582 .{ .name = ".debug_ranges", .index = wasm.debug_ranges_index },
2584 };2583 };
25852584
2586 for (debug_sections) |item| {2585 for (debug_sections) |item| {
2587 if (item.index) |index| {2586 if (item.index) |index| {
2588 var atom = self.atoms.get(index).?.getFirst();2587 var atom = wasm.atoms.get(index).?.getFirst();
2589 while (true) {2588 while (true) {
2590 atom.resolveRelocs(self);2589 atom.resolveRelocs(wasm);
2591 try debug_bytes.appendSlice(atom.code.items);2590 try debug_bytes.appendSlice(atom.code.items);
2592 atom = atom.next orelse break;2591 atom = atom.next orelse break;
2593 }2592 }
...@@ -2595,20 +2594,20 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2595,20 +2594,20 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2595 debug_bytes.clearRetainingCapacity();2594 debug_bytes.clearRetainingCapacity();
2596 }2595 }
2597 }2596 }
2598 try self.emitNameSection(&binary_bytes, arena);2597 try wasm.emitNameSection(&binary_bytes, arena);
2599 }2598 }
26002599
2601 // Only when writing all sections executed properly we write the magic2600 // Only when writing all sections executed properly we write the magic
2602 // bytes. This allows us to easily detect what went wrong while generating2601 // bytes. This allows us to easily detect what went wrong while generating
2603 // the final binary.2602 // 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
2606 // finally, write the entire binary into the file.2605 // finally, write the entire binary into the file.
2607 var iovec = [_]std.os.iovec_const{.{2606 var iovec = [_]std.os.iovec_const{.{
2608 .iov_base = binary_bytes.items.ptr,2607 .iov_base = binary_bytes.items.ptr,
2609 .iov_len = binary_bytes.items.len,2608 .iov_len = binary_bytes.items.len,
2610 }};2609 }};
2611 try self.base.file.?.writevAll(&iovec);2610 try wasm.base.file.?.writevAll(&iovec);
2612}2611}
26132612
2614fn emitDebugSection(binary_bytes: *std.ArrayList(u8), data: []const u8, name: []const u8) !void {2613fn 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: []...@@ -2629,7 +2628,7 @@ fn emitDebugSection(binary_bytes: *std.ArrayList(u8), data: []const u8, name: []
2629 );2628 );
2630}2629}
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 {
2633 const Name = struct {2632 const Name = struct {
2634 index: u32,2633 index: u32,
2635 name: []const u8,2634 name: []const u8,
...@@ -2642,15 +2641,15 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem...@@ -2642,15 +2641,15 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
26422641
2643 // we must de-duplicate symbols that point to the same function2642 // we must de-duplicate symbols that point to the same function
2644 var funcs = std.AutoArrayHashMap(u32, Name).init(arena);2643 var funcs = std.AutoArrayHashMap(u32, Name).init(arena);
2645 try funcs.ensureUnusedCapacity(self.functions.count() + self.imported_functions_count);2644 try funcs.ensureUnusedCapacity(wasm.functions.count() + wasm.imported_functions_count);
2646 var globals = try std.ArrayList(Name).initCapacity(arena, self.wasm_globals.items.len + self.imported_globals_count);2645 var globals = try std.ArrayList(Name).initCapacity(arena, wasm.wasm_globals.items.len + wasm.imported_globals_count);
2647 var segments = try std.ArrayList(Name).initCapacity(arena, self.data_segments.count());2646 var segments = try std.ArrayList(Name).initCapacity(arena, wasm.data_segments.count());
26482647
2649 for (self.resolved_symbols.keys()) |sym_loc| {2648 for (wasm.resolved_symbols.keys()) |sym_loc| {
2650 const symbol = sym_loc.getSymbol(self).*;2649 const symbol = sym_loc.getSymbol(wasm).*;
2651 const name = if (symbol.isUndefined()) blk: {2650 const name = if (symbol.isUndefined()) blk: {
2652 break :blk self.string_table.get(self.imports.get(sym_loc).?.name);2651 break :blk wasm.string_table.get(wasm.imports.get(sym_loc).?.name);
2653 } else sym_loc.getName(self);2652 } else sym_loc.getName(wasm);
2654 switch (symbol.tag) {2653 switch (symbol.tag) {
2655 .function => {2654 .function => {
2656 const gop = funcs.getOrPutAssumeCapacity(symbol.index);2655 const gop = funcs.getOrPutAssumeCapacity(symbol.index);
...@@ -2664,10 +2663,10 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem...@@ -2664,10 +2663,10 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
2664 }2663 }
2665 // data segments are already 'ordered'2664 // data segments are already 'ordered'
2666 var data_segment_index: u32 = 0;2665 var data_segment_index: u32 = 0;
2667 for (self.data_segments.keys()) |key| {2666 for (wasm.data_segments.keys()) |key| {
2668 // bss section is not emitted when this condition holds true, so we also2667 // bss section is not emitted when this condition holds true, so we also
2669 // do not output a name for it.2668 // 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;
2671 segments.appendAssumeCapacity(.{ .index = data_segment_index, .name = key });2670 segments.appendAssumeCapacity(.{ .index = data_segment_index, .name = key });
2672 data_segment_index += 1;2671 data_segment_index += 1;
2673 }2672 }
...@@ -2680,9 +2679,9 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem...@@ -2680,9 +2679,9 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
2680 try leb.writeULEB128(writer, @intCast(u32, "name".len));2679 try leb.writeULEB128(writer, @intCast(u32, "name".len));
2681 try writer.writeAll("name");2680 try writer.writeAll("name");
26822681
2683 try self.emitNameSubsection(.function, funcs.values(), writer);2682 try wasm.emitNameSubsection(.function, funcs.values(), writer);
2684 try self.emitNameSubsection(.global, globals.items, writer);2683 try wasm.emitNameSubsection(.global, globals.items, writer);
2685 try self.emitNameSubsection(.data_segment, segments.items, writer);2684 try wasm.emitNameSubsection(.data_segment, segments.items, writer);
26862685
2687 try writeCustomSectionHeader(2686 try writeCustomSectionHeader(
2688 binary_bytes.items,2687 binary_bytes.items,
...@@ -2691,9 +2690,9 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem...@@ -2691,9 +2690,9 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
2691 );2690 );
2692}2691}
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 {
2695 // We must emit subsection size, so first write to a temporary list2694 // 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);
2697 defer section_list.deinit();2696 defer section_list.deinit();
2698 const sub_writer = section_list.writer();2697 const sub_writer = section_list.writer();
26992698
...@@ -2711,7 +2710,7 @@ fn emitNameSubsection(self: *Wasm, section_id: std.wasm.NameSubsection, names: a...@@ -2711,7 +2710,7 @@ fn emitNameSubsection(self: *Wasm, section_id: std.wasm.NameSubsection, names: a
2711 try writer.writeAll(section_list.items);2710 try writer.writeAll(section_list.items);
2712}2711}
27132712
2714fn emitLimits(writer: anytype, limits: wasm.Limits) !void {2713fn emitLimits(writer: anytype, limits: std.wasm.Limits) !void {
2715 try leb.writeULEB128(writer, @boolToInt(limits.max != null));2714 try leb.writeULEB128(writer, @boolToInt(limits.max != null));
2716 try leb.writeULEB128(writer, limits.min);2715 try leb.writeULEB128(writer, limits.min);
2717 if (limits.max) |max| {2716 if (limits.max) |max| {
...@@ -2719,38 +2718,38 @@ fn emitLimits(writer: anytype, limits: wasm.Limits) !void {...@@ -2719,38 +2718,38 @@ fn emitLimits(writer: anytype, limits: wasm.Limits) !void {
2719 }2718 }
2720}2719}
27212720
2722fn emitInit(writer: anytype, init_expr: wasm.InitExpression) !void {2721fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void {
2723 switch (init_expr) {2722 switch (init_expr) {
2724 .i32_const => |val| {2723 .i32_const => |val| {
2725 try writer.writeByte(wasm.opcode(.i32_const));2724 try writer.writeByte(std.wasm.opcode(.i32_const));
2726 try leb.writeILEB128(writer, val);2725 try leb.writeILEB128(writer, val);
2727 },2726 },
2728 .i64_const => |val| {2727 .i64_const => |val| {
2729 try writer.writeByte(wasm.opcode(.i64_const));2728 try writer.writeByte(std.wasm.opcode(.i64_const));
2730 try leb.writeILEB128(writer, val);2729 try leb.writeILEB128(writer, val);
2731 },2730 },
2732 .f32_const => |val| {2731 .f32_const => |val| {
2733 try writer.writeByte(wasm.opcode(.f32_const));2732 try writer.writeByte(std.wasm.opcode(.f32_const));
2734 try writer.writeIntLittle(u32, @bitCast(u32, val));2733 try writer.writeIntLittle(u32, @bitCast(u32, val));
2735 },2734 },
2736 .f64_const => |val| {2735 .f64_const => |val| {
2737 try writer.writeByte(wasm.opcode(.f64_const));2736 try writer.writeByte(std.wasm.opcode(.f64_const));
2738 try writer.writeIntLittle(u64, @bitCast(u64, val));2737 try writer.writeIntLittle(u64, @bitCast(u64, val));
2739 },2738 },
2740 .global_get => |val| {2739 .global_get => |val| {
2741 try writer.writeByte(wasm.opcode(.global_get));2740 try writer.writeByte(std.wasm.opcode(.global_get));
2742 try leb.writeULEB128(writer, val);2741 try leb.writeULEB128(writer, val);
2743 },2742 },
2744 }2743 }
2745 try writer.writeByte(wasm.opcode(.end));2744 try writer.writeByte(std.wasm.opcode(.end));
2746}2745}
27472746
2748fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void {2747fn emitImport(wasm: *Wasm, writer: anytype, import: types.Import) !void {
2749 const module_name = self.string_table.get(import.module_name);2748 const module_name = wasm.string_table.get(import.module_name);
2750 try leb.writeULEB128(writer, @intCast(u32, module_name.len));2749 try leb.writeULEB128(writer, @intCast(u32, module_name.len));
2751 try writer.writeAll(module_name);2750 try writer.writeAll(module_name);
27522751
2753 const name = self.string_table.get(import.name);2752 const name = wasm.string_table.get(import.name);
2754 try leb.writeULEB128(writer, @intCast(u32, name.len));2753 try leb.writeULEB128(writer, @intCast(u32, name.len));
2755 try writer.writeAll(name);2754 try writer.writeAll(name);
27562755
...@@ -2758,11 +2757,11 @@ fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void {...@@ -2758,11 +2757,11 @@ fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void {
2758 switch (import.kind) {2757 switch (import.kind) {
2759 .function => |type_index| try leb.writeULEB128(writer, type_index),2758 .function => |type_index| try leb.writeULEB128(writer, type_index),
2760 .global => |global_type| {2759 .global => |global_type| {
2761 try leb.writeULEB128(writer, wasm.valtype(global_type.valtype));2760 try leb.writeULEB128(writer, std.wasm.valtype(global_type.valtype));
2762 try writer.writeByte(@boolToInt(global_type.mutable));2761 try writer.writeByte(@boolToInt(global_type.mutable));
2763 },2762 },
2764 .table => |table| {2763 .table => |table| {
2765 try leb.writeULEB128(writer, wasm.reftype(table.reftype));2764 try leb.writeULEB128(writer, std.wasm.reftype(table.reftype));
2766 try emitLimits(writer, table.limits);2765 try emitLimits(writer, table.limits);
2767 },2766 },
2768 .memory => |limits| {2767 .memory => |limits| {
...@@ -2771,28 +2770,28 @@ fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void {...@@ -2771,28 +2770,28 @@ fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void {
2771 }2770 }
2772}2771}
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 {
2775 const tracy = trace(@src());2774 const tracy = trace(@src());
2776 defer tracy.end();2775 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);
2779 defer arena_allocator.deinit();2778 defer arena_allocator.deinit();
2780 const arena = arena_allocator.allocator();2779 const arena = arena_allocator.allocator();
27812780
2782 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.2781 const directory = wasm.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});2782 const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.options.emit.?.sub_path});
27842783
2785 // If there is no Zig code to compile, then we should skip flushing the output file because it2784 // If there is no Zig code to compile, then we should skip flushing the output file because it
2786 // will not be part of the linker line anyway.2785 // will not be part of the linker line anyway.
2787 const module_obj_path: ?[]const u8 = if (self.base.options.module) |mod| blk: {2786 const module_obj_path: ?[]const u8 = if (wasm.base.options.module) |mod| blk: {
2788 const use_stage1 = build_options.have_stage1 and self.base.options.use_stage1;2787 const use_stage1 = build_options.have_stage1 and wasm.base.options.use_stage1;
2789 if (use_stage1) {2788 if (use_stage1) {
2790 const obj_basename = try std.zig.binNameAlloc(arena, .{2789 const obj_basename = try std.zig.binNameAlloc(arena, .{
2791 .root_name = self.base.options.root_name,2790 .root_name = wasm.base.options.root_name,
2792 .target = self.base.options.target,2791 .target = wasm.base.options.target,
2793 .output_mode = .Obj,2792 .output_mode = .Obj,
2794 });2793 });
2795 switch (self.base.options.cache_mode) {2794 switch (wasm.base.options.cache_mode) {
2796 .incremental => break :blk try mod.zig_cache_artifact_directory.join(2795 .incremental => break :blk try mod.zig_cache_artifact_directory.join(
2797 arena,2796 arena,
2798 &[_][]const u8{obj_basename},2797 &[_][]const u8{obj_basename},
...@@ -2803,12 +2802,12 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -2803,12 +2802,12 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
2803 }2802 }
2804 }2803 }
28052804
2806 try self.flushModule(comp, prog_node);2805 try wasm.flushModule(comp, prog_node);
28072806
2808 if (fs.path.dirname(full_out_path)) |dirname| {2807 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.? });
2810 } else {2809 } else {
2811 break :blk self.base.intermediary_basename.?;2810 break :blk wasm.base.intermediary_basename.?;
2812 }2811 }
2813 } else null;2812 } else null;
28142813
...@@ -2817,31 +2816,31 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -2817,31 +2816,31 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
2817 sub_prog_node.context.refresh();2816 sub_prog_node.context.refresh();
2818 defer sub_prog_node.end();2817 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)
2823 comp.compiler_rt_lib.?.full_object_path2822 comp.compiler_rt_lib.?.full_object_path
2824 else2823 else
2825 null;2824 null;
28262825
2827 const target = self.base.options.target;2826 const target = wasm.base.options.target;
28282827
2829 const id_symlink_basename = "lld.id";2828 const id_symlink_basename = "lld.id";
28302829
2831 var man: Cache.Manifest = undefined;2830 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
2834 var digest: [Cache.hex_digest_len]u8 = undefined;2833 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) {
2837 man = comp.cache_parent.obtain();2836 man = comp.cache_parent.obtain();
28382837
2839 // We are about to obtain this lock, so here we give other processes a chance first.2838 // 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
2842 comptime assert(Compilation.link_hash_implementation_version == 7);2841 comptime assert(Compilation.link_hash_implementation_version == 7);
28432842
2844 for (self.base.options.objects) |obj| {2843 for (wasm.base.options.objects) |obj| {
2845 _ = try man.addFile(obj.path, null);2844 _ = try man.addFile(obj.path, null);
2846 man.hash.add(obj.must_link);2845 man.hash.add(obj.must_link);
2847 }2846 }
...@@ -2850,18 +2849,18 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -2850,18 +2849,18 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
2850 }2849 }
2851 try man.addOptionalFile(module_obj_path);2850 try man.addOptionalFile(module_obj_path);
2852 try man.addOptionalFile(compiler_rt_path);2851 try man.addOptionalFile(compiler_rt_path);
2853 man.hash.addOptionalBytes(self.base.options.entry);2852 man.hash.addOptionalBytes(wasm.base.options.entry);
2854 man.hash.addOptional(self.base.options.stack_size_override);2853 man.hash.addOptional(wasm.base.options.stack_size_override);
2855 man.hash.add(self.base.options.import_memory);2854 man.hash.add(wasm.base.options.import_memory);
2856 man.hash.add(self.base.options.import_table);2855 man.hash.add(wasm.base.options.import_table);
2857 man.hash.add(self.base.options.export_table);2856 man.hash.add(wasm.base.options.export_table);
2858 man.hash.addOptional(self.base.options.initial_memory);2857 man.hash.addOptional(wasm.base.options.initial_memory);
2859 man.hash.addOptional(self.base.options.max_memory);2858 man.hash.addOptional(wasm.base.options.max_memory);
2860 man.hash.add(self.base.options.shared_memory);2859 man.hash.add(wasm.base.options.shared_memory);
2861 man.hash.addOptional(self.base.options.global_base);2860 man.hash.addOptional(wasm.base.options.global_base);
2862 man.hash.add(self.base.options.export_symbol_names.len);2861 man.hash.add(wasm.base.options.export_symbol_names.len);
2863 // strip does not need to go into the linker hash because it is part of the hash namespace2862 // 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| {
2865 man.hash.addBytes(symbol_name);2864 man.hash.addBytes(symbol_name);
2866 }2865 }
28672866
...@@ -2882,7 +2881,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -2882,7 +2881,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
2882 if (mem.eql(u8, prev_digest, &digest)) {2881 if (mem.eql(u8, prev_digest, &digest)) {
2883 log.debug("WASM LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});2882 log.debug("WASM LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
2884 // Hot diggity dog! The output binary is already there.2883 // Hot diggity dog! The output binary is already there.
2885 self.base.lock = man.toOwnedLock();2884 wasm.base.lock = man.toOwnedLock();
2886 return;2885 return;
2887 }2886 }
2888 log.debug("WASM LLD prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) });2887 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) !...@@ -2899,8 +2898,8 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
2899 // here. TODO: think carefully about how we can avoid this redundant operation when doing2898 // here. TODO: think carefully about how we can avoid this redundant operation when doing
2900 // build-obj. See also the corresponding TODO in linkAsArchive.2899 // build-obj. See also the corresponding TODO in linkAsArchive.
2901 const the_object_path = blk: {2900 const the_object_path = blk: {
2902 if (self.base.options.objects.len != 0)2901 if (wasm.base.options.objects.len != 0)
2903 break :blk self.base.options.objects[0].path;2902 break :blk wasm.base.options.objects[0].path;
29042903
2905 if (comp.c_object_table.count() != 0)2904 if (comp.c_object_table.count() != 0)
2906 break :blk comp.c_object_table.keys()[0].status.success.object_path;2905 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) !...@@ -2919,7 +2918,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
2919 }2918 }
2920 } else {2919 } else {
2921 // Create an LLD command line and invoke it.2920 // 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);
2923 defer argv.deinit();2922 defer argv.deinit();
2924 // We will invoke ourselves as a child process to gain access to LLD.2923 // We will invoke ourselves as a child process to gain access to LLD.
2925 // This is necessary because LLD does not behave properly as a library -2924 // 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) !...@@ -2927,47 +2926,47 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
2927 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, "wasm-ld" });2926 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, "wasm-ld" });
2928 try argv.append("-error-limit=0");2927 try argv.append("-error-limit=0");
29292928
2930 if (self.base.options.lto) {2929 if (wasm.base.options.lto) {
2931 switch (self.base.options.optimize_mode) {2930 switch (wasm.base.options.optimize_mode) {
2932 .Debug => {},2931 .Debug => {},
2933 .ReleaseSmall => try argv.append("-O2"),2932 .ReleaseSmall => try argv.append("-O2"),
2934 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),2933 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
2935 }2934 }
2936 }2935 }
29372936
2938 if (self.base.options.import_memory) {2937 if (wasm.base.options.import_memory) {
2939 try argv.append("--import-memory");2938 try argv.append("--import-memory");
2940 }2939 }
29412940
2942 if (self.base.options.import_table) {2941 if (wasm.base.options.import_table) {
2943 assert(!self.base.options.export_table);2942 assert(!wasm.base.options.export_table);
2944 try argv.append("--import-table");2943 try argv.append("--import-table");
2945 }2944 }
29462945
2947 if (self.base.options.export_table) {2946 if (wasm.base.options.export_table) {
2948 assert(!self.base.options.import_table);2947 assert(!wasm.base.options.import_table);
2949 try argv.append("--export-table");2948 try argv.append("--export-table");
2950 }2949 }
29512950
2952 if (self.base.options.strip) {2951 if (wasm.base.options.strip) {
2953 try argv.append("-s");2952 try argv.append("-s");
2954 }2953 }
29552954
2956 if (self.base.options.initial_memory) |initial_memory| {2955 if (wasm.base.options.initial_memory) |initial_memory| {
2957 const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});2956 const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});
2958 try argv.append(arg);2957 try argv.append(arg);
2959 }2958 }
29602959
2961 if (self.base.options.max_memory) |max_memory| {2960 if (wasm.base.options.max_memory) |max_memory| {
2962 const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});2961 const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});
2963 try argv.append(arg);2962 try argv.append(arg);
2964 }2963 }
29652964
2966 if (self.base.options.shared_memory) {2965 if (wasm.base.options.shared_memory) {
2967 try argv.append("--shared-memory");2966 try argv.append("--shared-memory");
2968 }2967 }
29692968
2970 if (self.base.options.global_base) |global_base| {2969 if (wasm.base.options.global_base) |global_base| {
2971 const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});2970 const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});
2972 try argv.append(arg);2971 try argv.append(arg);
2973 } else {2972 } else {
...@@ -2980,29 +2979,29 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -2980,29 +2979,29 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
29802979
2981 var auto_export_symbols = true;2980 var auto_export_symbols = true;
2982 // Users are allowed to specify which symbols they want to export to the wasm host.2981 // 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| {
2984 const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});2983 const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});
2985 try argv.append(arg);2984 try argv.append(arg);
2986 auto_export_symbols = false;2985 auto_export_symbols = false;
2987 }2986 }
29882987
2989 if (self.base.options.rdynamic) {2988 if (wasm.base.options.rdynamic) {
2990 try argv.append("--export-dynamic");2989 try argv.append("--export-dynamic");
2991 auto_export_symbols = false;2990 auto_export_symbols = false;
2992 }2991 }
29932992
2994 if (auto_export_symbols) {2993 if (auto_export_symbols) {
2995 if (self.base.options.module) |mod| {2994 if (wasm.base.options.module) |mod| {
2996 // when we use stage1, we use the exports that stage1 provided us.2995 // when we use stage1, we use the exports that stage1 provided us.
2997 // For stage2, we can directly retrieve them from the module.2996 // 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;
2999 if (use_stage1) {2998 if (use_stage1) {
3000 for (comp.export_symbol_names.items) |symbol_name| {2999 for (comp.export_symbol_names.items) |symbol_name| {
3001 try argv.append(try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}));3000 try argv.append(try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}));
3002 }3001 }
3003 } else {3002 } else {
3004 const skip_export_non_fn = target.os.tag == .wasi and3003 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;
3006 for (mod.decl_exports.values()) |exports| {3005 for (mod.decl_exports.values()) |exports| {
3007 for (exports) |exprt| {3006 for (exports) |exprt| {
3008 const exported_decl = mod.declPtr(exprt.exported_decl);3007 const exported_decl = mod.declPtr(exprt.exported_decl);
...@@ -3020,7 +3019,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3020,7 +3019,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3020 }3019 }
3021 }3020 }
30223021
3023 if (self.base.options.entry) |entry| {3022 if (wasm.base.options.entry) |entry| {
3024 try argv.append("--entry");3023 try argv.append("--entry");
3025 try argv.append(entry);3024 try argv.append(entry);
3026 }3025 }
...@@ -3028,16 +3027,16 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3028,16 +3027,16 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3028 // Increase the default stack size to a more reasonable value of 1MB instead of3027 // Increase the default stack size to a more reasonable value of 1MB instead of
3029 // the default of 1 Wasm page being 64KB, unless overridden by the user.3028 // the default of 1 Wasm page being 64KB, unless overridden by the user.
3030 try argv.append("-z");3029 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;
3032 const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size});3031 const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size});
3033 try argv.append(arg);3032 try argv.append(arg);
30343033
3035 if (self.base.options.output_mode == .Exe) {3034 if (wasm.base.options.output_mode == .Exe) {
3036 if (self.base.options.wasi_exec_model == .reactor) {3035 if (wasm.base.options.wasi_exec_model == .reactor) {
3037 // Reactor execution model does not have _start so lld doesn't look for it.3036 // Reactor execution model does not have _start so lld doesn't look for it.
3038 try argv.append("--no-entry");3037 try argv.append("--no-entry");
3039 }3038 }
3040 } else if (self.base.options.entry == null) {3039 } else if (wasm.base.options.entry == null) {
3041 try argv.append("--no-entry"); // So lld doesn't look for _start.3040 try argv.append("--no-entry"); // So lld doesn't look for _start.
3042 }3041 }
3043 try argv.appendSlice(&[_][]const u8{3042 try argv.appendSlice(&[_][]const u8{
...@@ -3051,10 +3050,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3051,10 +3050,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3051 }3050 }
30523051
3053 if (target.os.tag == .wasi) {3052 if (target.os.tag == .wasi) {
3054 const is_exe_or_dyn_lib = self.base.options.output_mode == .Exe or3053 const is_exe_or_dyn_lib = wasm.base.options.output_mode == .Exe or
3055 (self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic);3054 (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic);
3056 if (is_exe_or_dyn_lib) {3055 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;
3058 for (wasi_emulated_libs) |crt_file| {3057 for (wasi_emulated_libs) |crt_file| {
3059 try argv.append(try comp.get_libc_crt_file(3058 try argv.append(try comp.get_libc_crt_file(
3060 arena,3059 arena,
...@@ -3062,15 +3061,15 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3062,15 +3061,15 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3062 ));3061 ));
3063 }3062 }
30643063
3065 if (self.base.options.link_libc) {3064 if (wasm.base.options.link_libc) {
3066 try argv.append(try comp.get_libc_crt_file(3065 try argv.append(try comp.get_libc_crt_file(
3067 arena,3066 arena,
3068 wasi_libc.execModelCrtFileFullName(self.base.options.wasi_exec_model),3067 wasi_libc.execModelCrtFileFullName(wasm.base.options.wasi_exec_model),
3069 ));3068 ));
3070 try argv.append(try comp.get_libc_crt_file(arena, "libc.a"));3069 try argv.append(try comp.get_libc_crt_file(arena, "libc.a"));
3071 }3070 }
30723071
3073 if (self.base.options.link_libcpp) {3072 if (wasm.base.options.link_libcpp) {
3074 try argv.append(comp.libcxx_static_lib.?.full_object_path);3073 try argv.append(comp.libcxx_static_lib.?.full_object_path);
3075 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);3074 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
3076 }3075 }
...@@ -3079,7 +3078,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3079,7 +3078,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
30793078
3080 // Positional arguments to the linker such as object files.3079 // Positional arguments to the linker such as object files.
3081 var whole_archive = false;3080 var whole_archive = false;
3082 for (self.base.options.objects) |obj| {3081 for (wasm.base.options.objects) |obj| {
3083 if (obj.must_link and !whole_archive) {3082 if (obj.must_link and !whole_archive) {
3084 try argv.append("-whole-archive");3083 try argv.append("-whole-archive");
3085 whole_archive = true;3084 whole_archive = true;
...@@ -3101,9 +3100,9 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3101,9 +3100,9 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3101 try argv.append(p);3100 try argv.append(p);
3102 }3101 }
31033102
3104 if (self.base.options.output_mode != .Obj and3103 if (wasm.base.options.output_mode != .Obj and
3105 !self.base.options.skip_linker_dependencies and3104 !wasm.base.options.skip_linker_dependencies and
3106 !self.base.options.link_libc)3105 !wasm.base.options.link_libc)
3107 {3106 {
3108 try argv.append(comp.libc_static_lib.?.full_object_path);3107 try argv.append(comp.libc_static_lib.?.full_object_path);
3109 }3108 }
...@@ -3112,7 +3111,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3112,7 +3111,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3112 try argv.append(p);3111 try argv.append(p);
3113 }3112 }
31143113
3115 if (self.base.options.verbose_link) {3114 if (wasm.base.options.verbose_link) {
3116 // Skip over our own name so that the LLD linker name is the first argv item.3115 // Skip over our own name so that the LLD linker name is the first argv item.
3117 Compilation.dump_argv(argv.items[1..]);3116 Compilation.dump_argv(argv.items[1..]);
3118 }3117 }
...@@ -3129,7 +3128,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3129,7 +3128,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
31293128
3130 const term = child.spawnAndWait() catch |err| {3129 const term = child.spawnAndWait() catch |err| {
3131 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });3130 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
3132 return error.UnableToSpawnSelf;3131 return error.UnableToSpawnwasm;
3133 };3132 };
3134 switch (term) {3133 switch (term) {
3135 .Exited => |code| {3134 .Exited => |code| {
...@@ -3150,7 +3149,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3150,7 +3149,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
31503149
3151 const term = child.wait() catch |err| {3150 const term = child.wait() catch |err| {
3152 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });3151 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
3153 return error.UnableToSpawnSelf;3152 return error.UnableToSpawnwasm;
3154 };3153 };
31553154
3156 switch (term) {3155 switch (term) {
...@@ -3184,7 +3183,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -3184,7 +3183,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3184 }3183 }
3185 }3184 }
31863185
3187 if (!self.base.options.disable_lld_caching) {3186 if (!wasm.base.options.disable_lld_caching) {
3188 // Update the file with the digest. If it fails we can continue; it only3187 // Update the file with the digest. If it fails we can continue; it only
3189 // means that the next invocation will have an unnecessary cache miss.3188 // means that the next invocation will have an unnecessary cache miss.
3190 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {3189 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) !...@@ -3196,7 +3195,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
3196 };3195 };
3197 // We hang on to this lock so that the output file path can be used without3196 // We hang on to this lock so that the output file path can be used without
3198 // other processes clobbering it.3197 // other processes clobbering it.
3199 self.base.lock = man.toOwnedLock();3198 wasm.base.lock = man.toOwnedLock();
3200 }3199 }
3201}3200}
32023201
...@@ -3208,7 +3207,7 @@ fn reserveVecSectionHeader(bytes: *std.ArrayList(u8)) !u32 {...@@ -3208,7 +3207,7 @@ fn reserveVecSectionHeader(bytes: *std.ArrayList(u8)) !u32 {
3208 return offset;3207 return offset;
3209}3208}
32103209
3211fn reserveCustomSectionHeader(bytes: *std.ArrayList(u8)) !u64 {3210fn reserveCustomSectionHeader(bytes: *std.ArrayList(u8)) !u32 {
3212 // unlike regular section, we don't emit the count3211 // unlike regular section, we don't emit the count
3213 const header_size = 1 + 5;3212 const header_size = 1 + 5;
3214 const offset = @intCast(u32, bytes.items.len);3213 const offset = @intCast(u32, bytes.items.len);
...@@ -3216,7 +3215,7 @@ fn reserveCustomSectionHeader(bytes: *std.ArrayList(u8)) !u64 {...@@ -3216,7 +3215,7 @@ fn reserveCustomSectionHeader(bytes: *std.ArrayList(u8)) !u64 {
3216 return offset;3215 return offset;
3217}3216}
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 {
3220 var buf: [1 + 5 + 5]u8 = undefined;3219 var buf: [1 + 5 + 5]u8 = undefined;
3221 buf[0] = @enumToInt(section);3220 buf[0] = @enumToInt(section);
3222 leb.writeUnsignedFixed(5, buf[1..6], size);3221 leb.writeUnsignedFixed(5, buf[1..6], size);
...@@ -3224,14 +3223,14 @@ fn writeVecSectionHeader(buffer: []u8, offset: u32, section: wasm.Section, size:...@@ -3224,14 +3223,14 @@ fn writeVecSectionHeader(buffer: []u8, offset: u32, section: wasm.Section, size:
3224 mem.copy(u8, buffer[offset..], &buf);3223 mem.copy(u8, buffer[offset..], &buf);
3225}3224}
32263225
3227fn writeCustomSectionHeader(buffer: []u8, offset: u64, size: u32) !void {3226fn writeCustomSectionHeader(buffer: []u8, offset: u32, size: u32) !void {
3228 var buf: [1 + 5]u8 = undefined;3227 var buf: [1 + 5]u8 = undefined;
3229 buf[0] = 0; // 0 = 'custom' section3228 buf[0] = 0; // 0 = 'custom' section
3230 leb.writeUnsignedFixed(5, buf[1..6], size);3229 leb.writeUnsignedFixed(5, buf[1..6], size);
3231 mem.copy(u8, buffer[offset..], &buf);3230 mem.copy(u8, buffer[offset..], &buf);
3232}3231}
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 {
3235 const offset = try reserveCustomSectionHeader(binary_bytes);3234 const offset = try reserveCustomSectionHeader(binary_bytes);
3236 const writer = binary_bytes.writer();3235 const writer = binary_bytes.writer();
3237 // emit "linking" custom section name3236 // emit "linking" custom section name
...@@ -3244,22 +3243,22 @@ fn emitLinkSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:...@@ -3244,22 +3243,22 @@ fn emitLinkSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:
32443243
3245 // For each subsection type (found in types.Subsection) we can emit a section.3244 // For each subsection type (found in types.Subsection) we can emit a section.
3246 // Currently, we only support emitting segment info and the symbol table.3245 // Currently, we only support emitting segment info and the symbol table.
3247 try self.emitSymbolTable(binary_bytes, symbol_table);3246 try wasm.emitSymbolTable(binary_bytes, symbol_table);
3248 try self.emitSegmentInfo(binary_bytes);3247 try wasm.emitSegmentInfo(binary_bytes);
32493248
3250 const size = @intCast(u32, binary_bytes.items.len - offset - 6);3249 const size = @intCast(u32, binary_bytes.items.len - offset - 6);
3251 try writeCustomSectionHeader(binary_bytes.items, offset, size);3250 try writeCustomSectionHeader(binary_bytes.items, offset, size);
3252}3251}
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 {
3255 const writer = binary_bytes.writer();3254 const writer = binary_bytes.writer();
32563255
3257 try leb.writeULEB128(writer, @enumToInt(types.SubsectionType.WASM_SYMBOL_TABLE));3256 try leb.writeULEB128(writer, @enumToInt(types.SubsectionType.WASM_SYMBOL_TABLE));
3258 const table_offset = binary_bytes.items.len;3257 const table_offset = binary_bytes.items.len;
32593258
3260 var symbol_count: u32 = 0;3259 var symbol_count: u32 = 0;
3261 for (self.resolved_symbols.keys()) |sym_loc| {3260 for (wasm.resolved_symbols.keys()) |sym_loc| {
3262 const symbol = sym_loc.getSymbol(self).*;3261 const symbol = sym_loc.getSymbol(wasm).*;
3263 if (symbol.tag == .dead) continue; // Do not emit dead symbols3262 if (symbol.tag == .dead) continue; // Do not emit dead symbols
3264 try symbol_table.putNoClobber(sym_loc, symbol_count);3263 try symbol_table.putNoClobber(sym_loc, symbol_count);
3265 symbol_count += 1;3264 symbol_count += 1;
...@@ -3267,7 +3266,7 @@ fn emitSymbolTable(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:...@@ -3267,7 +3266,7 @@ fn emitSymbolTable(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:
3267 try leb.writeULEB128(writer, @enumToInt(symbol.tag));3266 try leb.writeULEB128(writer, @enumToInt(symbol.tag));
3268 try leb.writeULEB128(writer, symbol.flags);3267 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);
3271 switch (symbol.tag) {3270 switch (symbol.tag) {
3272 .data => {3271 .data => {
3273 try leb.writeULEB128(writer, @intCast(u32, sym_name.len));3272 try leb.writeULEB128(writer, @intCast(u32, sym_name.len));
...@@ -3275,7 +3274,7 @@ fn emitSymbolTable(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:...@@ -3275,7 +3274,7 @@ fn emitSymbolTable(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:
32753274
3276 if (symbol.isDefined()) {3275 if (symbol.isDefined()) {
3277 try leb.writeULEB128(writer, symbol.index);3276 try leb.writeULEB128(writer, symbol.index);
3278 const atom = self.symbol_atom.get(sym_loc).?;3277 const atom = wasm.symbol_atom.get(sym_loc).?;
3279 try leb.writeULEB128(writer, @as(u32, atom.offset));3278 try leb.writeULEB128(writer, @as(u32, atom.offset));
3280 try leb.writeULEB128(writer, @as(u32, atom.size));3279 try leb.writeULEB128(writer, @as(u32, atom.size));
3281 }3280 }
...@@ -3299,13 +3298,13 @@ fn emitSymbolTable(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:...@@ -3299,13 +3298,13 @@ fn emitSymbolTable(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:
3299 try binary_bytes.insertSlice(table_offset, &buf);3298 try binary_bytes.insertSlice(table_offset, &buf);
3300}3299}
33013300
3302fn emitSegmentInfo(self: *Wasm, binary_bytes: *std.ArrayList(u8)) !void {3301fn emitSegmentInfo(wasm: *Wasm, binary_bytes: *std.ArrayList(u8)) !void {
3303 const writer = binary_bytes.writer();3302 const writer = binary_bytes.writer();
3304 try leb.writeULEB128(writer, @enumToInt(types.SubsectionType.WASM_SEGMENT_INFO));3303 try leb.writeULEB128(writer, @enumToInt(types.SubsectionType.WASM_SEGMENT_INFO));
3305 const segment_offset = binary_bytes.items.len;3304 const segment_offset = binary_bytes.items.len;
33063305
3307 try leb.writeULEB128(writer, @intCast(u32, self.segment_info.count()));3306 try leb.writeULEB128(writer, @intCast(u32, wasm.segment_info.count()));
3308 for (self.segment_info.values()) |segment_info| {3307 for (wasm.segment_info.values()) |segment_info| {
3309 log.debug("Emit segment: {s} align({d}) flags({b})", .{3308 log.debug("Emit segment: {s} align({d}) flags({b})", .{
3310 segment_info.name,3309 segment_info.name,
3311 @ctz(segment_info.alignment),3310 @ctz(segment_info.alignment),
...@@ -3336,12 +3335,12 @@ pub fn getULEB128Size(uint_value: anytype) u32 {...@@ -3336,12 +3335,12 @@ pub fn getULEB128Size(uint_value: anytype) u32 {
33363335
3337/// For each relocatable section, emits a custom "relocation.<section_name>" section3336/// For each relocatable section, emits a custom "relocation.<section_name>" section
3338fn emitCodeRelocations(3337fn emitCodeRelocations(
3339 self: *Wasm,3338 wasm: *Wasm,
3340 binary_bytes: *std.ArrayList(u8),3339 binary_bytes: *std.ArrayList(u8),
3341 section_index: u32,3340 section_index: u32,
3342 symbol_table: std.AutoArrayHashMap(SymbolLoc, u32),3341 symbol_table: std.AutoArrayHashMap(SymbolLoc, u32),
3343) !void {3342) !void {
3344 const code_index = self.code_section_index orelse return;3343 const code_index = wasm.code_section_index orelse return;
3345 const writer = binary_bytes.writer();3344 const writer = binary_bytes.writer();
3346 const header_offset = try reserveCustomSectionHeader(binary_bytes);3345 const header_offset = try reserveCustomSectionHeader(binary_bytes);
33473346
...@@ -3353,7 +3352,7 @@ fn emitCodeRelocations(...@@ -3353,7 +3352,7 @@ fn emitCodeRelocations(
3353 const reloc_start = binary_bytes.items.len;3352 const reloc_start = binary_bytes.items.len;
33543353
3355 var count: u32 = 0;3354 var count: u32 = 0;
3356 var atom: *Atom = self.atoms.get(code_index).?.getFirst();3355 var atom: *Atom = wasm.atoms.get(code_index).?.getFirst();
3357 // for each atom, we calculate the uleb size and append that3356 // for each atom, we calculate the uleb size and append that
3358 var size_offset: u32 = 5; // account for code section size leb1283357 var size_offset: u32 = 5; // account for code section size leb128
3359 while (true) {3358 while (true) {
...@@ -3382,12 +3381,12 @@ fn emitCodeRelocations(...@@ -3382,12 +3381,12 @@ fn emitCodeRelocations(
3382}3381}
33833382
3384fn emitDataRelocations(3383fn emitDataRelocations(
3385 self: *Wasm,3384 wasm: *Wasm,
3386 binary_bytes: *std.ArrayList(u8),3385 binary_bytes: *std.ArrayList(u8),
3387 section_index: u32,3386 section_index: u32,
3388 symbol_table: std.AutoArrayHashMap(SymbolLoc, u32),3387 symbol_table: std.AutoArrayHashMap(SymbolLoc, u32),
3389) !void {3388) !void {
3390 if (self.data_segments.count() == 0) return;3389 if (wasm.data_segments.count() == 0) return;
3391 const writer = binary_bytes.writer();3390 const writer = binary_bytes.writer();
3392 const header_offset = try reserveCustomSectionHeader(binary_bytes);3391 const header_offset = try reserveCustomSectionHeader(binary_bytes);
33933392
...@@ -3401,8 +3400,8 @@ fn emitDataRelocations(...@@ -3401,8 +3400,8 @@ fn emitDataRelocations(
3401 var count: u32 = 0;3400 var count: u32 = 0;
3402 // for each atom, we calculate the uleb size and append that3401 // for each atom, we calculate the uleb size and append that
3403 var size_offset: u32 = 5; // account for code section size leb1283402 var size_offset: u32 = 5; // account for code section size leb128
3404 for (self.data_segments.values()) |segment_index| {3403 for (wasm.data_segments.values()) |segment_index| {
3405 var atom: *Atom = self.atoms.get(segment_index).?.getFirst();3404 var atom: *Atom = wasm.atoms.get(segment_index).?.getFirst();
3406 while (true) {3405 while (true) {
3407 size_offset += getULEB128Size(atom.size);3406 size_offset += getULEB128Size(atom.size);
3408 for (atom.relocs.items) |relocation| {3407 for (atom.relocs.items) |relocation| {
...@@ -3435,18 +3434,18 @@ fn emitDataRelocations(...@@ -3435,18 +3434,18 @@ fn emitDataRelocations(
34353434
3436/// Searches for an a matching function signature, when not found3435/// Searches for an a matching function signature, when not found
3437/// a new entry will be made. The index of the existing/new signature will be returned.3436/// 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 {
3439 var index: u32 = 0;3438 var index: u32 = 0;
3440 while (index < self.func_types.items.len) : (index += 1) {3439 while (index < wasm.func_types.items.len) : (index += 1) {
3441 if (self.func_types.items[index].eql(func_type)) return index;3440 if (wasm.func_types.items[index].eql(func_type)) return index;
3442 }3441 }
34433442
3444 // functype does not exist.3443 // functype does not exist.
3445 const params = try self.base.allocator.dupe(wasm.Valtype, func_type.params);3444 const params = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.params);
3446 errdefer self.base.allocator.free(params);3445 errdefer wasm.base.allocator.free(params);
3447 const returns = try self.base.allocator.dupe(wasm.Valtype, func_type.returns);3446 const returns = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.returns);
3448 errdefer self.base.allocator.free(returns);3447 errdefer wasm.base.allocator.free(returns);
3449 try self.func_types.append(self.base.allocator, .{3448 try wasm.func_types.append(wasm.base.allocator, .{
3450 .params = params,3449 .params = params,
3451 .returns = returns,3450 .returns = returns,
3452 });3451 });
src/link/Wasm/Archive.zig-1
...@@ -4,7 +4,6 @@ const std = @import("std");...@@ -4,7 +4,6 @@ const std = @import("std");
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const fs = std.fs;5const fs = std.fs;
6const log = std.log.scoped(.archive);6const log = std.log.scoped(.archive);
7const macho = std.macho;
8const mem = std.mem;7const mem = std.mem;
98
10const Allocator = mem.Allocator;9const Allocator = mem.Allocator;
src/link/Wasm/Atom.zig+36-36
...@@ -55,37 +55,37 @@ pub const empty: Atom = .{...@@ -55,37 +55,37 @@ pub const empty: Atom = .{
55};55};
5656
57/// Frees all resources owned by this `Atom`.57/// Frees all resources owned by this `Atom`.
58pub fn deinit(self: *Atom, gpa: Allocator) void {58pub fn deinit(atom: *Atom, gpa: Allocator) void {
59 self.relocs.deinit(gpa);59 atom.relocs.deinit(gpa);
60 self.code.deinit(gpa);60 atom.code.deinit(gpa);
6161
62 for (self.locals.items) |*local| {62 for (atom.locals.items) |*local| {
63 local.deinit(gpa);63 local.deinit(gpa);
64 }64 }
65 self.locals.deinit(gpa);65 atom.locals.deinit(gpa);
66}66}
6767
68/// Sets the length of relocations and code to '0',68/// Sets the length of relocations and code to '0',
69/// effectively resetting them and allowing them to be re-populated.69/// effectively resetting them and allowing them to be re-populated.
70pub fn clear(self: *Atom) void {70pub fn clear(atom: *Atom) void {
71 self.relocs.clearRetainingCapacity();71 atom.relocs.clearRetainingCapacity();
72 self.code.clearRetainingCapacity();72 atom.code.clearRetainingCapacity();
73}73}
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 {
76 _ = fmt;76 _ = fmt;
77 _ = options;77 _ = options;
78 try writer.print("Atom{{ .sym_index = {d}, .alignment = {d}, .size = {d}, .offset = 0x{x:0>8} }}", .{78 try writer.print("Atom{{ .sym_index = {d}, .alignment = {d}, .size = {d}, .offset = 0x{x:0>8} }}", .{
79 self.sym_index,79 atom.sym_index,
80 self.alignment,80 atom.alignment,
81 self.size,81 atom.size,
82 self.offset,82 atom.offset,
83 });83 });
84}84}
8585
86/// Returns the first `Atom` from a given atom86/// Returns the first `Atom` from a given atom
87pub fn getFirst(self: *Atom) *Atom {87pub fn getFirst(atom: *Atom) *Atom {
88 var tmp = self;88 var tmp = atom;
89 while (tmp.prev) |prev| tmp = prev;89 while (tmp.prev) |prev| tmp = prev;
90 return tmp;90 return tmp;
91}91}
...@@ -94,9 +94,9 @@ pub fn getFirst(self: *Atom) *Atom {...@@ -94,9 +94,9 @@ pub fn getFirst(self: *Atom) *Atom {
94/// produced from Zig code, rather than an object file.94/// produced from Zig code, rather than an object file.
95/// This is useful for debug sections where we want to extend95/// This is useful for debug sections where we want to extend
96/// the bytes, and don't want to overwrite existing Atoms.96/// the bytes, and don't want to overwrite existing Atoms.
97pub fn getFirstZigAtom(self: *Atom) *Atom {97pub fn getFirstZigAtom(atom: *Atom) *Atom {
98 if (self.file == null) return self;98 if (atom.file == null) return atom;
99 var tmp = self;99 var tmp = atom;
100 return while (tmp.prev) |prev| {100 return while (tmp.prev) |prev| {
101 if (prev.file == null) break prev;101 if (prev.file == null) break prev;
102 tmp = prev;102 tmp = prev;
...@@ -104,24 +104,24 @@ pub fn getFirstZigAtom(self: *Atom) *Atom {...@@ -104,24 +104,24 @@ pub fn getFirstZigAtom(self: *Atom) *Atom {
104}104}
105105
106/// Returns the location of the symbol that represents this `Atom`106/// Returns the location of the symbol that represents this `Atom`
107pub fn symbolLoc(self: Atom) Wasm.SymbolLoc {107pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {
108 return .{ .file = self.file, .index = self.sym_index };108 return .{ .file = atom.file, .index = atom.sym_index };
109}109}
110110
111/// Resolves the relocations within the atom, writing the new value111/// Resolves the relocations within the atom, writing the new value
112/// at the calculated offset.112/// at the calculated offset.
113pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {113pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
114 if (self.relocs.items.len == 0) return;114 if (atom.relocs.items.len == 0) return;
115 const symbol_name = self.symbolLoc().getName(wasm_bin);115 const symbol_name = atom.symbolLoc().getName(wasm_bin);
116 log.debug("Resolving relocs in atom '{s}' count({d})", .{116 log.debug("Resolving relocs in atom '{s}' count({d})", .{
117 symbol_name,117 symbol_name,
118 self.relocs.items.len,118 atom.relocs.items.len,
119 });119 });
120120
121 for (self.relocs.items) |reloc| {121 for (atom.relocs.items) |reloc| {
122 const value = self.relocationValue(reloc, wasm_bin);122 const value = atom.relocationValue(reloc, wasm_bin);
123 log.debug("Relocating '{s}' referenced in '{s}' offset=0x{x:0>8} value={d}", .{123 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),
125 symbol_name,125 symbol_name,
126 reloc.offset,126 reloc.offset,
127 value,127 value,
...@@ -133,10 +133,10 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {...@@ -133,10 +133,10 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {
133 .R_WASM_GLOBAL_INDEX_I32,133 .R_WASM_GLOBAL_INDEX_I32,
134 .R_WASM_MEMORY_ADDR_I32,134 .R_WASM_MEMORY_ADDR_I32,
135 .R_WASM_SECTION_OFFSET_I32,135 .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)),
137 .R_WASM_TABLE_INDEX_I64,137 .R_WASM_TABLE_INDEX_I64,
138 .R_WASM_MEMORY_ADDR_I64,138 .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),
140 .R_WASM_GLOBAL_INDEX_LEB,140 .R_WASM_GLOBAL_INDEX_LEB,
141 .R_WASM_EVENT_INDEX_LEB,141 .R_WASM_EVENT_INDEX_LEB,
142 .R_WASM_FUNCTION_INDEX_LEB,142 .R_WASM_FUNCTION_INDEX_LEB,
...@@ -145,11 +145,11 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {...@@ -145,11 +145,11 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {
145 .R_WASM_TABLE_INDEX_SLEB,145 .R_WASM_TABLE_INDEX_SLEB,
146 .R_WASM_TABLE_NUMBER_LEB,146 .R_WASM_TABLE_NUMBER_LEB,
147 .R_WASM_TYPE_INDEX_LEB,147 .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)),
149 .R_WASM_MEMORY_ADDR_LEB64,149 .R_WASM_MEMORY_ADDR_LEB64,
150 .R_WASM_MEMORY_ADDR_SLEB64,150 .R_WASM_MEMORY_ADDR_SLEB64,
151 .R_WASM_TABLE_INDEX_SLEB64,151 .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),
153 }153 }
154 }154 }
155}155}
...@@ -157,8 +157,8 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {...@@ -157,8 +157,8 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {
157/// From a given `relocation` will return the new value to be written.157/// From a given `relocation` will return the new value to be written.
158/// All values will be represented as a `u64` as all values can fit within it.158/// All values will be represented as a `u64` as all values can fit within it.
159/// The final value must be casted to the correct size.159/// The final value must be casted to the correct size.
160fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {160fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {
161 const target_loc = (Wasm.SymbolLoc{ .file = self.file, .index = relocation.index }).finalLoc(wasm_bin);161 const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin);
162 const symbol = target_loc.getSymbol(wasm_bin).*;162 const symbol = target_loc.getSymbol(wasm_bin).*;
163 switch (relocation.relocation_type) {163 switch (relocation.relocation_type) {
164 .R_WASM_FUNCTION_INDEX_LEB => return symbol.index,164 .R_WASM_FUNCTION_INDEX_LEB => return symbol.index,
...@@ -203,7 +203,7 @@ fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wa...@@ -203,7 +203,7 @@ fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wa
203 },203 },
204 .R_WASM_FUNCTION_OFFSET_I32 => {204 .R_WASM_FUNCTION_OFFSET_I32 => {
205 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;205 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
206 var atom = target_atom.getFirst();206 var current_atom = target_atom.getFirst();
207 var offset: u32 = 0;207 var offset: u32 = 0;
208 // TODO: Calculate this during atom allocation, rather than208 // TODO: Calculate this during atom allocation, rather than
209 // this linear calculation. For now it's done here as atoms209 // 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...@@ -211,8 +211,8 @@ fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wa
211 // merged until later.211 // merged until later.
212 while (true) {212 while (true) {
213 offset += 5; // each atom uses 5 bytes to store its body's size213 offset += 5; // each atom uses 5 bytes to store its body's size
214 if (atom == target_atom) break;214 if (current_atom == target_atom) break;
215 atom = atom.next.?;215 current_atom = current_atom.next.?;
216 }216 }
217 return target_atom.offset + offset + (relocation.addend orelse 0);217 return target_atom.offset + offset + (relocation.addend orelse 0);
218 },218 },
src/link/Wasm/Object.zig+114-114
...@@ -88,28 +88,28 @@ const RelocatableData = struct {...@@ -88,28 +88,28 @@ const RelocatableData = struct {
88 /// meta data of the given object file.88 /// meta data of the given object file.
89 /// NOTE: Alignment is encoded as a power of 2, so we shift the symbol's89 /// NOTE: Alignment is encoded as a power of 2, so we shift the symbol's
90 /// alignment to retrieve the natural alignment.90 /// alignment to retrieve the natural alignment.
91 pub fn getAlignment(self: RelocatableData, object: *const Object) u32 {91 pub fn getAlignment(relocatable_data: RelocatableData, object: *const Object) u32 {
92 if (self.type != .data) return 1;92 if (relocatable_data.type != .data) return 1;
93 const data_alignment = object.segment_info[self.index].alignment;93 const data_alignment = object.segment_info[relocatable_data.index].alignment;
94 if (data_alignment == 0) return 1;94 if (data_alignment == 0) return 1;
95 // Decode from power of 2 to natural alignment95 // Decode from power of 2 to natural alignment
96 return @as(u32, 1) << @intCast(u5, data_alignment);96 return @as(u32, 1) << @intCast(u5, data_alignment);
97 }97 }
9898
99 /// Returns the symbol kind that corresponds to the relocatable section99 /// Returns the symbol kind that corresponds to the relocatable section
100 pub fn getSymbolKind(self: RelocatableData) Symbol.Tag {100 pub fn getSymbolKind(relocatable_data: RelocatableData) Symbol.Tag {
101 return switch (self.type) {101 return switch (relocatable_data.type) {
102 .data => .data,102 .data => .data,
103 .code => .function,103 .code => .function,
104 .debug => .section,104 .debug => .section,
105 };105 };
106 }106 }
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,
109 /// returns the section index within the object file.109 /// returns the section index within the object file.
110 pub fn getIndex(self: RelocatableData) u32 {110 pub fn getIndex(relocatable_data: RelocatableData) u32 {
111 if (self.type == .debug) return self.section_index;111 if (relocatable_data.type == .debug) return relocatable_data.section_index;
112 return self.index;112 return relocatable_data.index;
113 }113 }
114};114};
115115
...@@ -153,51 +153,51 @@ pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8, maybe_max_siz...@@ -153,51 +153,51 @@ pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8, maybe_max_siz
153153
154/// Frees all memory of `Object` at once. The given `Allocator` must be154/// Frees all memory of `Object` at once. The given `Allocator` must be
155/// the same allocator that was used when `init` was called.155/// the same allocator that was used when `init` was called.
156pub fn deinit(self: *Object, gpa: Allocator) void {156pub fn deinit(object: *Object, gpa: Allocator) void {
157 if (self.file) |file| {157 if (object.file) |file| {
158 file.close();158 file.close();
159 }159 }
160 for (self.func_types) |func_ty| {160 for (object.func_types) |func_ty| {
161 gpa.free(func_ty.params);161 gpa.free(func_ty.params);
162 gpa.free(func_ty.returns);162 gpa.free(func_ty.returns);
163 }163 }
164 gpa.free(self.func_types);164 gpa.free(object.func_types);
165 gpa.free(self.functions);165 gpa.free(object.functions);
166 gpa.free(self.imports);166 gpa.free(object.imports);
167 gpa.free(self.tables);167 gpa.free(object.tables);
168 gpa.free(self.memories);168 gpa.free(object.memories);
169 gpa.free(self.globals);169 gpa.free(object.globals);
170 gpa.free(self.exports);170 gpa.free(object.exports);
171 for (self.elements) |el| {171 for (object.elements) |el| {
172 gpa.free(el.func_indexes);172 gpa.free(el.func_indexes);
173 }173 }
174 gpa.free(self.elements);174 gpa.free(object.elements);
175 gpa.free(self.features);175 gpa.free(object.features);
176 for (self.relocations.values()) |val| {176 for (object.relocations.values()) |val| {
177 gpa.free(val);177 gpa.free(val);
178 }178 }
179 self.relocations.deinit(gpa);179 object.relocations.deinit(gpa);
180 gpa.free(self.symtable);180 gpa.free(object.symtable);
181 gpa.free(self.comdat_info);181 gpa.free(object.comdat_info);
182 gpa.free(self.init_funcs);182 gpa.free(object.init_funcs);
183 for (self.segment_info) |info| {183 for (object.segment_info) |info| {
184 gpa.free(info.name);184 gpa.free(info.name);
185 }185 }
186 gpa.free(self.segment_info);186 gpa.free(object.segment_info);
187 for (self.relocatable_data) |rel_data| {187 for (object.relocatable_data) |rel_data| {
188 gpa.free(rel_data.data[0..rel_data.size]);188 gpa.free(rel_data.data[0..rel_data.size]);
189 }189 }
190 gpa.free(self.relocatable_data);190 gpa.free(object.relocatable_data);
191 self.string_table.deinit(gpa);191 object.string_table.deinit(gpa);
192 gpa.free(self.name);192 gpa.free(object.name);
193 self.* = undefined;193 object.* = undefined;
194}194}
195195
196/// Finds the import within the list of imports from a given kind and index of that kind.196/// Finds the import within the list of imports from a given kind and index of that kind.
197/// Asserts the import exists197/// 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 {
199 var i: u32 = 0;199 var i: u32 = 0;
200 return for (self.imports) |import| {200 return for (object.imports) |import| {
201 if (std.meta.activeTag(import.kind) == import_kind) {201 if (std.meta.activeTag(import.kind) == import_kind) {
202 if (i == index) return import;202 if (i == index) return import;
203 i += 1;203 i += 1;
...@@ -206,16 +206,16 @@ pub fn findImport(self: *const Object, import_kind: std.wasm.ExternalKind, index...@@ -206,16 +206,16 @@ pub fn findImport(self: *const Object, import_kind: std.wasm.ExternalKind, index
206}206}
207207
208/// Counts the entries of imported `kind` and returns the result208/// 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 {
210 var i: u32 = 0;210 var i: u32 = 0;
211 return for (self.imports) |imp| {211 return for (object.imports) |imp| {
212 if (@as(std.wasm.ExternalKind, imp.kind) == kind) i += 1;212 if (@as(std.wasm.ExternalKind, imp.kind) == kind) i += 1;
213 } else i;213 } else i;
214}214}
215215
216/// From a given `RelocatableDate`, find the corresponding debug section name216/// From a given `RelocatableDate`, find the corresponding debug section name
217pub fn getDebugName(self: *const Object, relocatable_data: RelocatableData) []const u8 {217pub fn getDebugName(object: *const Object, relocatable_data: RelocatableData) []const u8 {
218 return self.string_table.get(relocatable_data.index);218 return object.string_table.get(relocatable_data.index);
219}219}
220220
221/// Checks if the object file is an MVP version.221/// Checks if the object file is an MVP version.
...@@ -224,13 +224,13 @@ pub fn getDebugName(self: *const Object, relocatable_data: RelocatableData) []co...@@ -224,13 +224,13 @@ pub fn getDebugName(self: *const Object, relocatable_data: RelocatableData) []co
224/// we initialize a new table symbol that corresponds to that import and return that symbol.224/// we initialize a new table symbol that corresponds to that import and return that symbol.
225///225///
226/// When the object file is *NOT* MVP, we return `null`.226/// When the object file is *NOT* MVP, we return `null`.
227fn checkLegacyIndirectFunctionTable(self: *Object) !?Symbol {227fn checkLegacyIndirectFunctionTable(object: *Object) !?Symbol {
228 var table_count: usize = 0;228 var table_count: usize = 0;
229 for (self.symtable) |sym| {229 for (object.symtable) |sym| {
230 if (sym.tag == .table) table_count += 1;230 if (sym.tag == .table) table_count += 1;
231 }231 }
232232
233 const import_table_count = self.importedCountByKind(.table);233 const import_table_count = object.importedCountByKind(.table);
234234
235 // For each import table, we also have a symbol so this is not a legacy object file235 // For each import table, we also have a symbol so this is not a legacy object file
236 if (import_table_count == table_count) return null;236 if (import_table_count == table_count) return null;
...@@ -244,7 +244,7 @@ fn checkLegacyIndirectFunctionTable(self: *Object) !?Symbol {...@@ -244,7 +244,7 @@ fn checkLegacyIndirectFunctionTable(self: *Object) !?Symbol {
244 }244 }
245245
246 // MVP object files cannot have any table definitions, only imports (for the indirect function table).246 // 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) {
248 log.err("Unexpected table definition without representing table symbols.", .{});248 log.err("Unexpected table definition without representing table symbols.", .{});
249 return error.UnexpectedTable;249 return error.UnexpectedTable;
250 }250 }
...@@ -254,14 +254,14 @@ fn checkLegacyIndirectFunctionTable(self: *Object) !?Symbol {...@@ -254,14 +254,14 @@ fn checkLegacyIndirectFunctionTable(self: *Object) !?Symbol {
254 return error.MissingTableSymbols;254 return error.MissingTableSymbols;
255 }255 }
256256
257 var table_import: types.Import = for (self.imports) |imp| {257 var table_import: types.Import = for (object.imports) |imp| {
258 if (imp.kind == .table) {258 if (imp.kind == .table) {
259 break imp;259 break imp;
260 }260 }
261 } else unreachable;261 } else unreachable;
262262
263 if (!std.mem.eql(u8, self.string_table.get(table_import.name), "__indirect_function_table")) {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", .{self.string_table.get(table_import.name)});264 log.err("Non-indirect function table import '{s}' is missing a corresponding symbol", .{object.string_table.get(table_import.name)});
265 return error.MissingTableSymbols;265 return error.MissingTableSymbols;
266 }266 }
267267
...@@ -313,41 +313,41 @@ pub const ParseError = error{...@@ -313,41 +313,41 @@ pub const ParseError = error{
313 UnknownFeature,313 UnknownFeature,
314};314};
315315
316fn parse(self: *Object, gpa: Allocator, reader: anytype, is_object_file: *bool) Parser(@TypeOf(reader)).Error!void {316fn parse(object: *Object, gpa: Allocator, reader: anytype, is_object_file: *bool) Parser(@TypeOf(reader)).Error!void {
317 var parser = Parser(@TypeOf(reader)).init(self, reader);317 var parser = Parser(@TypeOf(reader)).init(object, reader);
318 return parser.parseObject(gpa, is_object_file);318 return parser.parseObject(gpa, is_object_file);
319}319}
320320
321fn Parser(comptime ReaderType: type) type {321fn Parser(comptime ReaderType: type) type {
322 return struct {322 return struct {
323 const Self = @This();323 const ObjectParser = @This();
324 const Error = ReaderType.Error || ParseError;324 const Error = ReaderType.Error || ParseError;
325325
326 reader: std.io.CountingReader(ReaderType),326 reader: std.io.CountingReader(ReaderType),
327 /// Object file we're building327 /// Object file we're building
328 object: *Object,328 object: *Object,
329329
330 fn init(object: *Object, reader: ReaderType) Self {330 fn init(object: *Object, reader: ReaderType) ObjectParser {
331 return .{ .object = object, .reader = std.io.countingReader(reader) };331 return .{ .object = object, .reader = std.io.countingReader(reader) };
332 }332 }
333333
334 /// Verifies that the first 4 bytes contains \0Asm334 /// Verifies that the first 4 bytes contains \0Asm
335 fn verifyMagicBytes(self: *Self) Error!void {335 fn verifyMagicBytes(parser: *ObjectParser) Error!void {
336 var magic_bytes: [4]u8 = undefined;336 var magic_bytes: [4]u8 = undefined;
337337
338 try self.reader.reader().readNoEof(&magic_bytes);338 try parser.reader.reader().readNoEof(&magic_bytes);
339 if (!std.mem.eql(u8, &magic_bytes, &std.wasm.magic)) {339 if (!std.mem.eql(u8, &magic_bytes, &std.wasm.magic)) {
340 log.debug("Invalid magic bytes '{s}'", .{&magic_bytes});340 log.debug("Invalid magic bytes '{s}'", .{&magic_bytes});
341 return error.InvalidMagicByte;341 return error.InvalidMagicByte;
342 }342 }
343 }343 }
344344
345 fn parseObject(self: *Self, gpa: Allocator, is_object_file: *bool) Error!void {345 fn parseObject(parser: *ObjectParser, gpa: Allocator, is_object_file: *bool) Error!void {
346 errdefer self.object.deinit(gpa);346 errdefer parser.object.deinit(gpa);
347 try self.verifyMagicBytes();347 try parser.verifyMagicBytes();
348 const version = try self.reader.reader().readIntLittle(u32);348 const version = try parser.reader.reader().readIntLittle(u32);
349349
350 self.object.version = version;350 parser.object.version = version;
351 var relocatable_data = std.ArrayList(RelocatableData).init(gpa);351 var relocatable_data = std.ArrayList(RelocatableData).init(gpa);
352 var debug_names = std.ArrayList(u8).init(gpa);352 var debug_names = std.ArrayList(u8).init(gpa);
353353
...@@ -360,9 +360,9 @@ fn Parser(comptime ReaderType: type) type {...@@ -360,9 +360,9 @@ fn Parser(comptime ReaderType: type) type {
360 }360 }
361361
362 var section_index: u32 = 0;362 var section_index: u32 = 0;
363 while (self.reader.reader().readByte()) |byte| : (section_index += 1) {363 while (parser.reader.reader().readByte()) |byte| : (section_index += 1) {
364 const len = try readLeb(u32, self.reader.reader());364 const len = try readLeb(u32, parser.reader.reader());
365 var limited_reader = std.io.limitedReader(self.reader.reader(), len);365 var limited_reader = std.io.limitedReader(parser.reader.reader(), len);
366 const reader = limited_reader.reader();366 const reader = limited_reader.reader();
367 switch (@intToEnum(std.wasm.Section, byte)) {367 switch (@intToEnum(std.wasm.Section, byte)) {
368 .custom => {368 .custom => {
...@@ -373,12 +373,12 @@ fn Parser(comptime ReaderType: type) type {...@@ -373,12 +373,12 @@ fn Parser(comptime ReaderType: type) type {
373373
374 if (std.mem.eql(u8, name, "linking")) {374 if (std.mem.eql(u8, name, "linking")) {
375 is_object_file.* = true;375 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.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 self.parseMetadata(gpa, @intCast(usize, reader.context.bytes_left));377 try parser.parseMetadata(gpa, @intCast(usize, reader.context.bytes_left));
378 } else if (std.mem.startsWith(u8, name, "reloc")) {378 } else if (std.mem.startsWith(u8, name, "reloc")) {
379 try self.parseRelocations(gpa);379 try parser.parseRelocations(gpa);
380 } else if (std.mem.eql(u8, name, "target_features")) {380 } else if (std.mem.eql(u8, name, "target_features")) {
381 try self.parseFeatures(gpa);381 try parser.parseFeatures(gpa);
382 } else if (std.mem.startsWith(u8, name, ".debug")) {382 } else if (std.mem.startsWith(u8, name, ".debug")) {
383 const debug_size = @intCast(u32, reader.context.bytes_left);383 const debug_size = @intCast(u32, reader.context.bytes_left);
384 const debug_content = try gpa.alloc(u8, debug_size);384 const debug_content = try gpa.alloc(u8, debug_size);
...@@ -389,7 +389,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -389,7 +389,7 @@ fn Parser(comptime ReaderType: type) type {
389 .type = .debug,389 .type = .debug,
390 .data = debug_content.ptr,390 .data = debug_content.ptr,
391 .size = debug_size,391 .size = debug_size,
392 .index = try self.object.string_table.put(gpa, name),392 .index = try parser.object.string_table.put(gpa, name),
393 .offset = 0, // debug sections only contain 1 entry, so no need to calculate offset393 .offset = 0, // debug sections only contain 1 entry, so no need to calculate offset
394 .section_index = section_index,394 .section_index = section_index,
395 });395 });
...@@ -398,7 +398,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -398,7 +398,7 @@ fn Parser(comptime ReaderType: type) type {
398 }398 }
399 },399 },
400 .type => {400 .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| {
402 if ((try reader.readByte()) != std.wasm.function_type) return error.ExpectedFuncType;402 if ((try reader.readByte()) != std.wasm.function_type) return error.ExpectedFuncType;
403403
404 for (try readVec(&type_val.params, reader, gpa)) |*param| {404 for (try readVec(&type_val.params, reader, gpa)) |*param| {
...@@ -412,7 +412,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -412,7 +412,7 @@ fn Parser(comptime ReaderType: type) type {
412 try assertEnd(reader);412 try assertEnd(reader);
413 },413 },
414 .import => {414 .import => {
415 for (try readVec(&self.object.imports, reader, gpa)) |*import| {415 for (try readVec(&parser.object.imports, reader, gpa)) |*import| {
416 const module_len = try readLeb(u32, reader);416 const module_len = try readLeb(u32, reader);
417 const module_name = try gpa.alloc(u8, module_len);417 const module_name = try gpa.alloc(u8, module_len);
418 defer gpa.free(module_name);418 defer gpa.free(module_name);
...@@ -438,21 +438,21 @@ fn Parser(comptime ReaderType: type) type {...@@ -438,21 +438,21 @@ fn Parser(comptime ReaderType: type) type {
438 };438 };
439439
440 import.* = .{440 import.* = .{
441 .module_name = try self.object.string_table.put(gpa, module_name),441 .module_name = try parser.object.string_table.put(gpa, module_name),
442 .name = try self.object.string_table.put(gpa, name),442 .name = try parser.object.string_table.put(gpa, name),
443 .kind = kind_value,443 .kind = kind_value,
444 };444 };
445 }445 }
446 try assertEnd(reader);446 try assertEnd(reader);
447 },447 },
448 .function => {448 .function => {
449 for (try readVec(&self.object.functions, reader, gpa)) |*func| {449 for (try readVec(&parser.object.functions, reader, gpa)) |*func| {
450 func.* = .{ .type_index = try readLeb(u32, reader) };450 func.* = .{ .type_index = try readLeb(u32, reader) };
451 }451 }
452 try assertEnd(reader);452 try assertEnd(reader);
453 },453 },
454 .table => {454 .table => {
455 for (try readVec(&self.object.tables, reader, gpa)) |*table| {455 for (try readVec(&parser.object.tables, reader, gpa)) |*table| {
456 table.* = .{456 table.* = .{
457 .reftype = try readEnum(std.wasm.RefType, reader),457 .reftype = try readEnum(std.wasm.RefType, reader),
458 .limits = try readLimits(reader),458 .limits = try readLimits(reader),
...@@ -461,13 +461,13 @@ fn Parser(comptime ReaderType: type) type {...@@ -461,13 +461,13 @@ fn Parser(comptime ReaderType: type) type {
461 try assertEnd(reader);461 try assertEnd(reader);
462 },462 },
463 .memory => {463 .memory => {
464 for (try readVec(&self.object.memories, reader, gpa)) |*memory| {464 for (try readVec(&parser.object.memories, reader, gpa)) |*memory| {
465 memory.* = .{ .limits = try readLimits(reader) };465 memory.* = .{ .limits = try readLimits(reader) };
466 }466 }
467 try assertEnd(reader);467 try assertEnd(reader);
468 },468 },
469 .global => {469 .global => {
470 for (try readVec(&self.object.globals, reader, gpa)) |*global| {470 for (try readVec(&parser.object.globals, reader, gpa)) |*global| {
471 global.* = .{471 global.* = .{
472 .global_type = .{472 .global_type = .{
473 .valtype = try readEnum(std.wasm.Valtype, reader),473 .valtype = try readEnum(std.wasm.Valtype, reader),
...@@ -479,13 +479,13 @@ fn Parser(comptime ReaderType: type) type {...@@ -479,13 +479,13 @@ fn Parser(comptime ReaderType: type) type {
479 try assertEnd(reader);479 try assertEnd(reader);
480 },480 },
481 .@"export" => {481 .@"export" => {
482 for (try readVec(&self.object.exports, reader, gpa)) |*exp| {482 for (try readVec(&parser.object.exports, reader, gpa)) |*exp| {
483 const name_len = try readLeb(u32, reader);483 const name_len = try readLeb(u32, reader);
484 const name = try gpa.alloc(u8, name_len);484 const name = try gpa.alloc(u8, name_len);
485 defer gpa.free(name);485 defer gpa.free(name);
486 try reader.readNoEof(name);486 try reader.readNoEof(name);
487 exp.* = .{487 exp.* = .{
488 .name = try self.object.string_table.put(gpa, name),488 .name = try parser.object.string_table.put(gpa, name),
489 .kind = try readEnum(std.wasm.ExternalKind, reader),489 .kind = try readEnum(std.wasm.ExternalKind, reader),
490 .index = try readLeb(u32, reader),490 .index = try readLeb(u32, reader),
491 };491 };
...@@ -493,11 +493,11 @@ fn Parser(comptime ReaderType: type) type {...@@ -493,11 +493,11 @@ fn Parser(comptime ReaderType: type) type {
493 try assertEnd(reader);493 try assertEnd(reader);
494 },494 },
495 .start => {495 .start => {
496 self.object.start = try readLeb(u32, reader);496 parser.object.start = try readLeb(u32, reader);
497 try assertEnd(reader);497 try assertEnd(reader);
498 },498 },
499 .element => {499 .element => {
500 for (try readVec(&self.object.elements, reader, gpa)) |*elem| {500 for (try readVec(&parser.object.elements, reader, gpa)) |*elem| {
501 elem.table_index = try readLeb(u32, reader);501 elem.table_index = try readLeb(u32, reader);
502 elem.offset = try readInit(reader);502 elem.offset = try readInit(reader);
503503
...@@ -521,7 +521,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -521,7 +521,7 @@ fn Parser(comptime ReaderType: type) type {
521 .type = .code,521 .type = .code,
522 .data = data.ptr,522 .data = data.ptr,
523 .size = code_len,523 .size = code_len,
524 .index = self.object.importedCountByKind(.function) + index,524 .index = parser.object.importedCountByKind(.function) + index,
525 .offset = offset,525 .offset = offset,
526 .section_index = section_index,526 .section_index = section_index,
527 });527 });
...@@ -551,22 +551,22 @@ fn Parser(comptime ReaderType: type) type {...@@ -551,22 +551,22 @@ fn Parser(comptime ReaderType: type) type {
551 });551 });
552 }552 }
553 },553 },
554 else => try self.reader.reader().skipBytes(len, .{}),554 else => try parser.reader.reader().skipBytes(len, .{}),
555 }555 }
556 } else |err| switch (err) {556 } else |err| switch (err) {
557 error.EndOfStream => {}, // finished parsing the file557 error.EndOfStream => {}, // finished parsing the file
558 else => |e| return e,558 else => |e| return e,
559 }559 }
560 self.object.relocatable_data = relocatable_data.toOwnedSlice();560 parser.object.relocatable_data = relocatable_data.toOwnedSlice();
561 }561 }
562562
563 /// Based on the "features" custom section, parses it into a list of563 /// Based on the "features" custom section, parses it into a list of
564 /// features that tell the linker what features were enabled and may be mandatory564 /// features that tell the linker what features were enabled and may be mandatory
565 /// to be able to link.565 /// to be able to link.
566 /// Logs an info message when an undefined feature is detected.566 /// Logs an info message when an undefined feature is detected.
567 fn parseFeatures(self: *Self, gpa: Allocator) !void {567 fn parseFeatures(parser: *ObjectParser, gpa: Allocator) !void {
568 const reader = self.reader.reader();568 const reader = parser.reader.reader();
569 for (try readVec(&self.object.features, reader, gpa)) |*feature| {569 for (try readVec(&parser.object.features, reader, gpa)) |*feature| {
570 const prefix = try readEnum(types.Feature.Prefix, reader);570 const prefix = try readEnum(types.Feature.Prefix, reader);
571 const name_len = try leb.readULEB128(u32, reader);571 const name_len = try leb.readULEB128(u32, reader);
572 const name = try gpa.alloc(u8, name_len);572 const name = try gpa.alloc(u8, name_len);
...@@ -587,8 +587,8 @@ fn Parser(comptime ReaderType: type) type {...@@ -587,8 +587,8 @@ fn Parser(comptime ReaderType: type) type {
587 /// Parses a "reloc" custom section into a list of relocations.587 /// Parses a "reloc" custom section into a list of relocations.
588 /// The relocations are mapped into `Object` where the key is the section588 /// The relocations are mapped into `Object` where the key is the section
589 /// they apply to.589 /// they apply to.
590 fn parseRelocations(self: *Self, gpa: Allocator) !void {590 fn parseRelocations(parser: *ObjectParser, gpa: Allocator) !void {
591 const reader = self.reader.reader();591 const reader = parser.reader.reader();
592 const section = try leb.readULEB128(u32, reader);592 const section = try leb.readULEB128(u32, reader);
593 const count = try leb.readULEB128(u32, reader);593 const count = try leb.readULEB128(u32, reader);
594 const relocations = try gpa.alloc(types.Relocation, count);594 const relocations = try gpa.alloc(types.Relocation, count);
...@@ -616,15 +616,15 @@ fn Parser(comptime ReaderType: type) type {...@@ -616,15 +616,15 @@ fn Parser(comptime ReaderType: type) type {
616 });616 });
617 }617 }
618618
619 try self.object.relocations.putNoClobber(gpa, section, relocations);619 try parser.object.relocations.putNoClobber(gpa, section, relocations);
620 }620 }
621621
622 /// Parses the "linking" custom section. Versions that are not622 /// Parses the "linking" custom section. Versions that are not
623 /// supported will be an error. `payload_size` is required to be able623 /// supported will be an error. `payload_size` is required to be able
624 /// to calculate the subsections we need to parse, as that data is not624 /// to calculate the subsections we need to parse, as that data is not
625 /// available within the section itself.625 /// available within the section itparser.
626 fn parseMetadata(self: *Self, gpa: Allocator, payload_size: usize) !void {626 fn parseMetadata(parser: *ObjectParser, gpa: Allocator, payload_size: usize) !void {
627 var limited = std.io.limitedReader(self.reader.reader(), payload_size);627 var limited = std.io.limitedReader(parser.reader.reader(), payload_size);
628 const limited_reader = limited.reader();628 const limited_reader = limited.reader();
629629
630 const version = try leb.readULEB128(u32, limited_reader);630 const version = try leb.readULEB128(u32, limited_reader);
...@@ -632,7 +632,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -632,7 +632,7 @@ fn Parser(comptime ReaderType: type) type {
632 if (version != 2) return error.UnsupportedVersion;632 if (version != 2) return error.UnsupportedVersion;
633633
634 while (limited.bytes_left > 0) {634 while (limited.bytes_left > 0) {
635 try self.parseSubsection(gpa, limited_reader);635 try parser.parseSubsection(gpa, limited_reader);
636 }636 }
637 }637 }
638638
...@@ -640,9 +640,9 @@ fn Parser(comptime ReaderType: type) type {...@@ -640,9 +640,9 @@ fn Parser(comptime ReaderType: type) type {
640 /// The `reader` param for this is to provide a `LimitedReader`, which allows640 /// The `reader` param for this is to provide a `LimitedReader`, which allows
641 /// us to only read until a max length.641 /// us to only read until a max length.
642 ///642 ///
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,
644 /// such as access to the `import` section to find the name of a symbol.644 /// 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 {
646 const sub_type = try leb.readULEB128(u8, reader);646 const sub_type = try leb.readULEB128(u8, reader);
647 log.debug("Found subsection: {s}", .{@tagName(@intToEnum(types.SubsectionType, sub_type))});647 log.debug("Found subsection: {s}", .{@tagName(@intToEnum(types.SubsectionType, sub_type))});
648 const payload_len = try leb.readULEB128(u32, reader);648 const payload_len = try leb.readULEB128(u32, reader);
...@@ -674,7 +674,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -674,7 +674,7 @@ fn Parser(comptime ReaderType: type) type {
674 segment.flags,674 segment.flags,
675 });675 });
676 }676 }
677 self.object.segment_info = segments;677 parser.object.segment_info = segments;
678 },678 },
679 .WASM_INIT_FUNCS => {679 .WASM_INIT_FUNCS => {
680 const funcs = try gpa.alloc(types.InitFunc, count);680 const funcs = try gpa.alloc(types.InitFunc, count);
...@@ -686,7 +686,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -686,7 +686,7 @@ fn Parser(comptime ReaderType: type) type {
686 };686 };
687 log.debug("Found function - prio: {d}, index: {d}", .{ func.priority, func.symbol_index });687 log.debug("Found function - prio: {d}, index: {d}", .{ func.priority, func.symbol_index });
688 }688 }
689 self.object.init_funcs = funcs;689 parser.object.init_funcs = funcs;
690 },690 },
691 .WASM_COMDAT_INFO => {691 .WASM_COMDAT_INFO => {
692 const comdats = try gpa.alloc(types.Comdat, count);692 const comdats = try gpa.alloc(types.Comdat, count);
...@@ -719,7 +719,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -719,7 +719,7 @@ fn Parser(comptime ReaderType: type) type {
719 };719 };
720 }720 }
721721
722 self.object.comdat_info = comdats;722 parser.object.comdat_info = comdats;
723 },723 },
724 .WASM_SYMBOL_TABLE => {724 .WASM_SYMBOL_TABLE => {
725 var symbols = try std.ArrayList(Symbol).initCapacity(gpa, count);725 var symbols = try std.ArrayList(Symbol).initCapacity(gpa, count);
...@@ -727,22 +727,22 @@ fn Parser(comptime ReaderType: type) type {...@@ -727,22 +727,22 @@ fn Parser(comptime ReaderType: type) type {
727 var i: usize = 0;727 var i: usize = 0;
728 while (i < count) : (i += 1) {728 while (i < count) : (i += 1) {
729 const symbol = symbols.addOneAssumeCapacity();729 const symbol = symbols.addOneAssumeCapacity();
730 symbol.* = try self.parseSymbol(gpa, reader);730 symbol.* = try parser.parseSymbol(gpa, reader);
731 log.debug("Found symbol: type({s}) name({s}) flags(0b{b:0>8})", .{731 log.debug("Found symbol: type({s}) name({s}) flags(0b{b:0>8})", .{
732 @tagName(symbol.tag),732 @tagName(symbol.tag),
733 self.object.string_table.get(symbol.name),733 parser.object.string_table.get(symbol.name),
734 symbol.flags,734 symbol.flags,
735 });735 });
736 }736 }
737737
738 // we found all symbols, check for indirect function table738 // we found all symbols, check for indirect function table
739 // in case of an MVP object file739 // in case of an MVP object file
740 if (try self.object.checkLegacyIndirectFunctionTable()) |symbol| {740 if (try parser.object.checkLegacyIndirectFunctionTable()) |symbol| {
741 try symbols.append(symbol);741 try symbols.append(symbol);
742 log.debug("Found legacy indirect function table. Created symbol", .{});742 log.debug("Found legacy indirect function table. Created symbol", .{});
743 }743 }
744744
745 self.object.symtable = symbols.toOwnedSlice();745 parser.object.symtable = symbols.toOwnedSlice();
746 },746 },
747 }747 }
748 }748 }
...@@ -750,7 +750,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -750,7 +750,7 @@ fn Parser(comptime ReaderType: type) type {
750 /// Parses the symbol information based on its kind,750 /// Parses the symbol information based on its kind,
751 /// requires access to `Object` to find the name of a symbol when it's751 /// requires access to `Object` to find the name of a symbol when it's
752 /// an import and flag `WASM_SYM_EXPLICIT_NAME` is not set.752 /// 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 {
754 const tag = @intToEnum(Symbol.Tag, try leb.readULEB128(u8, reader));754 const tag = @intToEnum(Symbol.Tag, try leb.readULEB128(u8, reader));
755 const flags = try leb.readULEB128(u32, reader);755 const flags = try leb.readULEB128(u32, reader);
756 var symbol: Symbol = .{756 var symbol: Symbol = .{
...@@ -766,7 +766,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -766,7 +766,7 @@ fn Parser(comptime ReaderType: type) type {
766 const name = try gpa.alloc(u8, name_len);766 const name = try gpa.alloc(u8, name_len);
767 defer gpa.free(name);767 defer gpa.free(name);
768 try reader.readNoEof(name);768 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
771 // Data symbols only have the following fields if the symbol is defined771 // Data symbols only have the following fields if the symbol is defined
772 if (symbol.isDefined()) {772 if (symbol.isDefined()) {
...@@ -778,7 +778,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -778,7 +778,7 @@ fn Parser(comptime ReaderType: type) type {
778 },778 },
779 .section => {779 .section => {
780 symbol.index = try leb.readULEB128(u32, reader);780 symbol.index = try leb.readULEB128(u32, reader);
781 for (self.object.relocatable_data) |data| {781 for (parser.object.relocatable_data) |data| {
782 if (data.section_index == symbol.index) {782 if (data.section_index == symbol.index) {
783 symbol.name = data.index;783 symbol.name = data.index;
784 break;784 break;
...@@ -791,7 +791,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -791,7 +791,7 @@ fn Parser(comptime ReaderType: type) type {
791791
792 const is_undefined = symbol.isUndefined();792 const is_undefined = symbol.isUndefined();
793 if (is_undefined) {793 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);
795 }795 }
796 const explicit_name = symbol.hasFlag(.WASM_SYM_EXPLICIT_NAME);796 const explicit_name = symbol.hasFlag(.WASM_SYM_EXPLICIT_NAME);
797 if (!(is_undefined and !explicit_name)) {797 if (!(is_undefined and !explicit_name)) {
...@@ -799,7 +799,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -799,7 +799,7 @@ fn Parser(comptime ReaderType: type) type {
799 const name = try gpa.alloc(u8, name_len);799 const name = try gpa.alloc(u8, name_len);
800 defer gpa.free(name);800 defer gpa.free(name);
801 try reader.readNoEof(name);801 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);
803 } else {803 } else {
804 symbol.name = maybe_import.?.name;804 symbol.name = maybe_import.?.name;
805 }805 }
...@@ -872,7 +872,7 @@ fn assertEnd(reader: anytype) !void {...@@ -872,7 +872,7 @@ fn assertEnd(reader: anytype) !void {
872}872}
873873
874/// Parses an object file into atoms, for code and data sections874/// 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 {
876 const Key = struct {876 const Key = struct {
877 kind: Symbol.Tag,877 kind: Symbol.Tag,
878 index: u32,878 index: u32,
...@@ -882,7 +882,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin...@@ -882,7 +882,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
882 list.deinit();882 list.deinit();
883 } else symbol_for_segment.deinit();883 } else symbol_for_segment.deinit();
884884
885 for (self.symtable) |symbol, symbol_index| {885 for (object.symtable) |symbol, symbol_index| {
886 switch (symbol.tag) {886 switch (symbol.tag) {
887 .function, .data, .section => if (!symbol.isUndefined()) {887 .function, .data, .section => if (!symbol.isUndefined()) {
888 const gop = try symbol_for_segment.getOrPut(.{ .kind = symbol.tag, .index = symbol.index });888 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...@@ -896,7 +896,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
896 }896 }
897 }897 }
898898
899 for (self.relocatable_data) |relocatable_data, index| {899 for (object.relocatable_data) |relocatable_data, index| {
900 const final_index = (try wasm_bin.getMatchingSegment(object_index, @intCast(u32, index))) orelse {900 const final_index = (try wasm_bin.getMatchingSegment(object_index, @intCast(u32, index))) orelse {
901 continue; // found unknown section, so skip parsing into atom as we do not know how to handle it.901 continue; // found unknown section, so skip parsing into atom as we do not know how to handle it.
902 };902 };
...@@ -911,12 +911,12 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin...@@ -911,12 +911,12 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
911 try wasm_bin.managed_atoms.append(gpa, atom);911 try wasm_bin.managed_atoms.append(gpa, atom);
912 atom.file = object_index;912 atom.file = object_index;
913 atom.size = relocatable_data.size;913 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 &.{};
917 for (relocations) |relocation| {917 for (relocations) |relocation| {
918 if (isInbetween(relocatable_data.offset, atom.size, relocation.offset)) {918 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,
920 // rather than within the entire section.920 // rather than within the entire section.
921 var reloc = relocation;921 var reloc = relocation;
922 reloc.offset -= relocatable_data.offset;922 reloc.offset -= relocatable_data.offset;
...@@ -942,8 +942,8 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin...@@ -942,8 +942,8 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
942 // symbols referencing the same atom will be added as alias942 // symbols referencing the same atom will be added as alias
943 // or as 'parent' when they are global.943 // or as 'parent' when they are global.
944 while (symbols.popOrNull()) |idx| {944 while (symbols.popOrNull()) |idx| {
945 const alias_symbol = self.symtable[idx];945 const alias_symbol = object.symtable[idx];
946 const symbol = self.symtable[atom.sym_index];946 const symbol = object.symtable[atom.sym_index];
947 if (alias_symbol.isGlobal() and symbol.isLocal()) {947 if (alias_symbol.isGlobal() and symbol.isLocal()) {
948 atom.sym_index = idx;948 atom.sym_index = idx;
949 }949 }
...@@ -957,7 +957,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin...@@ -957,7 +957,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
957 }957 }
958958
959 try wasm_bin.appendAtomAtIndex(final_index, atom);959 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 });
961 }961 }
962}962}
963963
src/link/Wasm/Symbol.zig+44-44
...@@ -34,8 +34,8 @@ pub const Tag = enum {...@@ -34,8 +34,8 @@ pub const Tag = enum {
3434
35 /// From a given symbol tag, returns the `ExternalType`35 /// From a given symbol tag, returns the `ExternalType`
36 /// Asserts the given tag can be represented as an external type.36 /// Asserts the given tag can be represented as an external type.
37 pub fn externalType(self: Tag) std.wasm.ExternalKind {37 pub fn externalType(tag: Tag) std.wasm.ExternalKind {
38 return switch (self) {38 return switch (tag) {
39 .function => .function,39 .function => .function,
40 .global => .global,40 .global => .global,
41 .data => .memory,41 .data => .memory,
...@@ -78,85 +78,85 @@ pub const Flag = enum(u32) {...@@ -78,85 +78,85 @@ pub const Flag = enum(u32) {
7878
79/// Verifies if the given symbol should be imported from the79/// Verifies if the given symbol should be imported from the
80/// host environment or not80/// host environment or not
81pub fn requiresImport(self: Symbol) bool {81pub fn requiresImport(symbol: Symbol) bool {
82 if (self.tag == .data) return false;82 if (symbol.tag == .data) return false;
83 if (!self.isUndefined()) return false;83 if (!symbol.isUndefined()) return false;
84 if (self.isWeak()) return false;84 if (symbol.isWeak()) return false;
85 // if (self.isDefined() and self.isWeak()) return true; //TODO: Only when building shared lib85 // if (symbol.isDefined() and symbol.isWeak()) return true; //TODO: Only when building shared lib
8686
87 return true;87 return true;
88}88}
8989
90pub fn hasFlag(self: Symbol, flag: Flag) bool {90pub fn hasFlag(symbol: Symbol, flag: Flag) bool {
91 return self.flags & @enumToInt(flag) != 0;91 return symbol.flags & @enumToInt(flag) != 0;
92}92}
9393
94pub fn setFlag(self: *Symbol, flag: Flag) void {94pub fn setFlag(symbol: *Symbol, flag: Flag) void {
95 self.flags |= @enumToInt(flag);95 symbol.flags |= @enumToInt(flag);
96}96}
9797
98pub fn isUndefined(self: Symbol) bool {98pub fn isUndefined(symbol: Symbol) bool {
99 return self.flags & @enumToInt(Flag.WASM_SYM_UNDEFINED) != 0;99 return symbol.flags & @enumToInt(Flag.WASM_SYM_UNDEFINED) != 0;
100}100}
101101
102pub fn setUndefined(self: *Symbol, is_undefined: bool) void {102pub fn setUndefined(symbol: *Symbol, is_undefined: bool) void {
103 if (is_undefined) {103 if (is_undefined) {
104 self.setFlag(.WASM_SYM_UNDEFINED);104 symbol.setFlag(.WASM_SYM_UNDEFINED);
105 } else {105 } else {
106 self.flags &= ~@enumToInt(Flag.WASM_SYM_UNDEFINED);106 symbol.flags &= ~@enumToInt(Flag.WASM_SYM_UNDEFINED);
107 }107 }
108}108}
109109
110pub fn setGlobal(self: *Symbol, is_global: bool) void {110pub fn setGlobal(symbol: *Symbol, is_global: bool) void {
111 if (is_global) {111 if (is_global) {
112 self.flags &= ~@enumToInt(Flag.WASM_SYM_BINDING_LOCAL);112 symbol.flags &= ~@enumToInt(Flag.WASM_SYM_BINDING_LOCAL);
113 } else {113 } else {
114 self.setFlag(.WASM_SYM_BINDING_LOCAL);114 symbol.setFlag(.WASM_SYM_BINDING_LOCAL);
115 }115 }
116}116}
117117
118pub fn isDefined(self: Symbol) bool {118pub fn isDefined(symbol: Symbol) bool {
119 return !self.isUndefined();119 return !symbol.isUndefined();
120}120}
121121
122pub fn isVisible(self: Symbol) bool {122pub fn isVisible(symbol: Symbol) bool {
123 return self.flags & @enumToInt(Flag.WASM_SYM_VISIBILITY_HIDDEN) == 0;123 return symbol.flags & @enumToInt(Flag.WASM_SYM_VISIBILITY_HIDDEN) == 0;
124}124}
125125
126pub fn isLocal(self: Symbol) bool {126pub fn isLocal(symbol: Symbol) bool {
127 return self.flags & @enumToInt(Flag.WASM_SYM_BINDING_LOCAL) != 0;127 return symbol.flags & @enumToInt(Flag.WASM_SYM_BINDING_LOCAL) != 0;
128}128}
129129
130pub fn isGlobal(self: Symbol) bool {130pub fn isGlobal(symbol: Symbol) bool {
131 return self.flags & @enumToInt(Flag.WASM_SYM_BINDING_LOCAL) == 0;131 return symbol.flags & @enumToInt(Flag.WASM_SYM_BINDING_LOCAL) == 0;
132}132}
133133
134pub fn isHidden(self: Symbol) bool {134pub fn isHidden(symbol: Symbol) bool {
135 return self.flags & @enumToInt(Flag.WASM_SYM_VISIBILITY_HIDDEN) != 0;135 return symbol.flags & @enumToInt(Flag.WASM_SYM_VISIBILITY_HIDDEN) != 0;
136}136}
137137
138pub fn isNoStrip(self: Symbol) bool {138pub fn isNoStrip(symbol: Symbol) bool {
139 return self.flags & @enumToInt(Flag.WASM_SYM_NO_STRIP) != 0;139 return symbol.flags & @enumToInt(Flag.WASM_SYM_NO_STRIP) != 0;
140}140}
141141
142pub fn isExported(self: Symbol) bool {142pub fn isExported(symbol: Symbol) bool {
143 if (self.isUndefined() or self.isLocal()) return false;143 if (symbol.isUndefined() or symbol.isLocal()) return false;
144 if (self.isHidden()) return false;144 if (symbol.isHidden()) return false;
145 if (self.hasFlag(.WASM_SYM_EXPORTED)) return true;145 if (symbol.hasFlag(.WASM_SYM_EXPORTED)) return true;
146 if (self.hasFlag(.WASM_SYM_BINDING_WEAK)) return false;146 if (symbol.hasFlag(.WASM_SYM_BINDING_WEAK)) return false;
147 return true;147 return true;
148}148}
149149
150pub fn isWeak(self: Symbol) bool {150pub fn isWeak(symbol: Symbol) bool {
151 return self.flags & @enumToInt(Flag.WASM_SYM_BINDING_WEAK) != 0;151 return symbol.flags & @enumToInt(Flag.WASM_SYM_BINDING_WEAK) != 0;
152}152}
153153
154/// Formats the symbol into human-readable text154/// 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 {
156 _ = fmt;156 _ = fmt;
157 _ = options;157 _ = options;
158158
159 const kind_fmt: u8 = switch (self.tag) {159 const kind_fmt: u8 = switch (symbol.tag) {
160 .function => 'F',160 .function => 'F',
161 .data => 'D',161 .data => 'D',
162 .global => 'G',162 .global => 'G',
...@@ -165,12 +165,12 @@ pub fn format(self: Symbol, comptime fmt: []const u8, options: std.fmt.FormatOpt...@@ -165,12 +165,12 @@ pub fn format(self: Symbol, comptime fmt: []const u8, options: std.fmt.FormatOpt
165 .table => 'T',165 .table => 'T',
166 .dead => '-',166 .dead => '-',
167 };167 };
168 const visible: []const u8 = if (self.isVisible()) "yes" else "no";168 const visible: []const u8 = if (symbol.isVisible()) "yes" else "no";
169 const binding: []const u8 = if (self.isLocal()) "local" else "global";169 const binding: []const u8 = if (symbol.isLocal()) "local" else "global";
170 const undef: []const u8 = if (self.isUndefined()) "undefined" else "";170 const undef: []const u8 = if (symbol.isUndefined()) "undefined" else "";
171171
172 try writer.print(172 try writer.print(
173 "{c} binding={s} visible={s} id={d} name_offset={d} {s}",173 "{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 },
175 );175 );
176}176}
src/link/Wasm/types.zig+5-5
...@@ -202,22 +202,22 @@ pub const Feature = struct {...@@ -202,22 +202,22 @@ pub const Feature = struct {
202 required = '=',202 required = '=',
203 };203 };
204204
205 pub fn toString(self: Feature) []const u8 {205 pub fn toString(feature: Feature) []const u8 {
206 return switch (self.tag) {206 return switch (feature.tag) {
207 .bulk_memory => "bulk-memory",207 .bulk_memory => "bulk-memory",
208 .exception_handling => "exception-handling",208 .exception_handling => "exception-handling",
209 .mutable_globals => "mutable-globals",209 .mutable_globals => "mutable-globals",
210 .nontrapping_fptoint => "nontrapping-fptoint",210 .nontrapping_fptoint => "nontrapping-fptoint",
211 .sign_ext => "sign-ext",211 .sign_ext => "sign-ext",
212 .tail_call => "tail-call",212 .tail_call => "tail-call",
213 else => @tagName(self),213 else => @tagName(feature),
214 };214 };
215 }215 }
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 {
218 _ = opt;218 _ = opt;
219 _ = fmt;219 _ = fmt;
220 try writer.print("{c} {s}", .{ self.prefix, self.toString() });220 try writer.print("{c} {s}", .{ feature.prefix, feature.toString() });
221 }221 }
222};222};
223223