authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 19:11:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 19:49:08-07:00
logd5c1e7f7b1381036f7d98c1944607cb0e1c0d4da
treef78506c79713b855ed8f23426ce78e0e292e13ee
parenteae6d45cded76dd027569c86a7cdd5bc9039664b

link: accept the update arena in flush

This branch introduced an arena allocator for temporary allocations in Compilation.update. Almost every implementation of flush() inside the linker code was already creating a local arena that had the lifetime of the function call. This commit passes the update arena so that all those local ones can be deleted, resulting in slightly more efficient memory usage with every compilation update. While at it, this commit also removes the Compilation parameter from the linker flush function API since a reference to the Compilation is now already stored in `link.File`.

12 files changed, 108 insertions(+), 119 deletions(-)

src/Compilation.zig+1-1
...@@ -2311,7 +2311,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2311,7 +2311,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2311fn flush(comp: *Compilation, arena: Allocator, prog_node: *std.Progress.Node) !void {2311fn flush(comp: *Compilation, arena: Allocator, prog_node: *std.Progress.Node) !void {
2312 if (comp.bin_file) |lf| {2312 if (comp.bin_file) |lf| {
2313 // This is needed before reading the error flags.2313 // This is needed before reading the error flags.
2314 lf.flush(comp, prog_node) catch |err| switch (err) {2314 lf.flush(arena, prog_node) catch |err| switch (err) {
2315 error.FlushFailure => {}, // error reported through link_error_flags2315 error.FlushFailure => {}, // error reported through link_error_flags
2316 error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr2316 error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr
2317 else => |e| return e,2317 else => |e| return e,
src/link.zig+15-14
...@@ -547,19 +547,22 @@ pub const File = struct {...@@ -547,19 +547,22 @@ pub const File = struct {
547547
548 /// Commit pending changes and write headers. Takes into account final output mode548 /// Commit pending changes and write headers. Takes into account final output mode
549 /// and `use_lld`, not only `effectiveOutputMode`.549 /// and `use_lld`, not only `effectiveOutputMode`.
550 pub fn flush(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void {550 /// `arena` has the lifetime of the call to `Compilation.update`.
551 pub fn flush(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void {
551 if (build_options.only_c) {552 if (build_options.only_c) {
552 assert(base.tag == .c);553 assert(base.tag == .c);
553 return @fieldParentPtr(C, "base", base).flush(comp, prog_node);554 return @fieldParentPtr(C, "base", base).flush(arena, prog_node);
554 }555 }
556 const comp = base.comp;
555 if (comp.clang_preprocessor_mode == .yes) {557 if (comp.clang_preprocessor_mode == .yes) {
558 const gpa = comp.gpa;
556 const emit = base.emit;559 const emit = base.emit;
557 // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)560 // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)
558 // Until then, we do `lld -r -o output.o input.o` even though the output is the same561 // Until then, we do `lld -r -o output.o input.o` even though the output is the same
559 // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file562 // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file
560 // to the final location. See also the corresponding TODO in Coff linking.563 // to the final location. See also the corresponding TODO in Coff linking.
561 const full_out_path = try emit.directory.join(comp.gpa, &[_][]const u8{emit.sub_path});564 const full_out_path = try emit.directory.join(gpa, &[_][]const u8{emit.sub_path});
562 defer comp.gpa.free(full_out_path);565 defer gpa.free(full_out_path);
563 assert(comp.c_object_table.count() == 1);566 assert(comp.c_object_table.count() == 1);
564 const the_key = comp.c_object_table.keys()[0];567 const the_key = comp.c_object_table.keys()[0];
565 const cached_pp_file_path = the_key.status.success.object_path;568 const cached_pp_file_path = the_key.status.success.object_path;
...@@ -571,25 +574,25 @@ pub const File = struct {...@@ -571,25 +574,25 @@ pub const File = struct {
571 const output_mode = comp.config.output_mode;574 const output_mode = comp.config.output_mode;
572 const link_mode = comp.config.link_mode;575 const link_mode = comp.config.link_mode;
573 if (use_lld and output_mode == .Lib and link_mode == .Static) {576 if (use_lld and output_mode == .Lib and link_mode == .Static) {
574 return base.linkAsArchive(comp, prog_node);577 return base.linkAsArchive(arena, prog_node);
575 }578 }
576 switch (base.tag) {579 switch (base.tag) {
577 inline else => |tag| {580 inline else => |tag| {
578 return @fieldParentPtr(tag.Type(), "base", base).flush(comp, prog_node);581 return @fieldParentPtr(tag.Type(), "base", base).flush(arena, prog_node);
579 },582 },
580 }583 }
581 }584 }
582585
583 /// Commit pending changes and write headers. Works based on `effectiveOutputMode`586 /// Commit pending changes and write headers. Works based on `effectiveOutputMode`
584 /// rather than final output mode.587 /// rather than final output mode.
585 pub fn flushModule(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void {588 pub fn flushModule(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void {
586 switch (base.tag) {589 switch (base.tag) {
587 .c => {590 .c => {
588 return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node);591 return @fieldParentPtr(C, "base", base).flushModule(arena, prog_node);
589 },592 },
590 inline else => |tag| {593 inline else => |tag| {
591 if (build_options.only_c) unreachable;594 if (build_options.only_c) unreachable;
592 return @fieldParentPtr(tag.Type(), "base", base).flushModule(comp, prog_node);595 return @fieldParentPtr(tag.Type(), "base", base).flushModule(arena, prog_node);
593 },596 },
594 }597 }
595 }598 }
...@@ -707,14 +710,12 @@ pub const File = struct {...@@ -707,14 +710,12 @@ pub const File = struct {
707 }710 }
708 }711 }
709712
710 pub fn linkAsArchive(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void {713 pub fn linkAsArchive(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void {
711 const tracy = trace(@src());714 const tracy = trace(@src());
712 defer tracy.end();715 defer tracy.end();
713716
717 const comp = base.comp;
714 const gpa = comp.gpa;718 const gpa = comp.gpa;
715 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
716 defer arena_allocator.deinit();
717 const arena = arena_allocator.allocator();
718719
719 const directory = base.emit.directory; // Just an alias to make it shorter to type.720 const directory = base.emit.directory; // Just an alias to make it shorter to type.
720 const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});721 const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
...@@ -724,7 +725,7 @@ pub const File = struct {...@@ -724,7 +725,7 @@ pub const File = struct {
724 // If there is no Zig code to compile, then we should skip flushing the output file725 // If there is no Zig code to compile, then we should skip flushing the output file
725 // because it will not be part of the linker line anyway.726 // because it will not be part of the linker line anyway.
726 const zcu_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {727 const zcu_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {
727 try base.flushModule(comp, prog_node);728 try base.flushModule(arena, prog_node);
728729
729 const dirname = fs.path.dirname(full_out_path_z) orelse ".";730 const dirname = fs.path.dirname(full_out_path_z) orelse ".";
730 break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? });731 break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? });
src/link/C.zig+7-4
...@@ -376,8 +376,8 @@ pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: InternPool.De...@@ -376,8 +376,8 @@ pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: InternPool.De
376 _ = decl_index;376 _ = decl_index;
377}377}
378378
379pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void {379pub fn flush(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !void {
380 return self.flushModule(comp, prog_node);380 return self.flushModule(arena, prog_node);
381}381}
382382
383fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {383fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
...@@ -393,7 +393,9 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {...@@ -393,7 +393,9 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
393 return defines;393 return defines;
394}394}
395395
396pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !void {396pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !void {
397 _ = arena; // Has the same lifetime as the call to Compilation.update.
398
397 const tracy = trace(@src());399 const tracy = trace(@src());
398 defer tracy.end();400 defer tracy.end();
399401
...@@ -401,7 +403,8 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo...@@ -401,7 +403,8 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
401 sub_prog_node.activate();403 sub_prog_node.activate();
402 defer sub_prog_node.end();404 defer sub_prog_node.end();
403405
404 const gpa = self.base.comp.gpa;406 const comp = self.base.comp;
407 const gpa = comp.gpa;
405 const module = self.base.comp.module.?;408 const module = self.base.comp.module.?;
406409
407 {410 {
src/link/Coff.zig+8-10
...@@ -1706,28 +1706,26 @@ fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void {...@@ -1706,28 +1706,26 @@ fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void {
1706 gop.value_ptr.* = current;1706 gop.value_ptr.* = current;
1707}1707}
17081708
1709pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {1709pub fn flush(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
1710 const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;1710 const comp = self.base.comp;
1711 const use_lld = build_options.have_llvm and comp.config.use_lld;
1711 if (use_lld) {1712 if (use_lld) {
1712 return lld.linkWithLLD(self, comp, prog_node);1713 return lld.linkWithLLD(self, arena, prog_node);
1713 }1714 }
1714 switch (self.base.comp.config.output_mode) {1715 switch (comp.config.output_mode) {
1715 .Exe, .Obj => return self.flushModule(comp, prog_node),1716 .Exe, .Obj => return self.flushModule(arena, prog_node),
1716 .Lib => return error.TODOImplementWritingLibFiles,1717 .Lib => return error.TODOImplementWritingLibFiles,
1717 }1718 }
1718}1719}
17191720
1720pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {1721pub fn flushModule(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
1721 const tracy = trace(@src());1722 const tracy = trace(@src());
1722 defer tracy.end();1723 defer tracy.end();
17231724
1725 const comp = self.base.comp;
1724 const gpa = comp.gpa;1726 const gpa = comp.gpa;
17251727
1726 if (self.llvm_object) |llvm_object| {1728 if (self.llvm_object) |llvm_object| {
1727 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
1728 defer arena_allocator.deinit();
1729 const arena = arena_allocator.allocator();
1730
1731 try self.base.emitLlvmObject(arena, llvm_object, prog_node);1729 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
1732 return;1730 return;
1733 }1731 }
src/link/Coff/lld.zig+3-5
...@@ -17,14 +17,12 @@ const Allocator = mem.Allocator;...@@ -17,14 +17,12 @@ const Allocator = mem.Allocator;
17const Coff = @import("../Coff.zig");17const Coff = @import("../Coff.zig");
18const Compilation = @import("../../Compilation.zig");18const Compilation = @import("../../Compilation.zig");
1919
20pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {20pub fn linkWithLLD(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) !void {
21 const tracy = trace(@src());21 const tracy = trace(@src());
22 defer tracy.end();22 defer tracy.end();
2323
24 const comp = self.base.comp;
24 const gpa = comp.gpa;25 const gpa = comp.gpa;
25 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
26 defer arena_allocator.deinit();
27 const arena = arena_allocator.allocator();
2826
29 const directory = self.base.emit.directory; // Just an alias to make it shorter to type.27 const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
30 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});28 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
...@@ -32,7 +30,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -32,7 +30,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
32 // If there is no Zig code to compile, then we should skip flushing the output file because it30 // If there is no Zig code to compile, then we should skip flushing the output file because it
33 // will not be part of the linker line anyway.31 // will not be part of the linker line anyway.
34 const module_obj_path: ?[]const u8 = if (comp.module != null) blk: {32 const module_obj_path: ?[]const u8 = if (comp.module != null) blk: {
35 try self.flushModule(comp, prog_node);33 try self.flushModule(arena, prog_node);
3634
37 if (fs.path.dirname(full_out_path)) |dirname| {35 if (fs.path.dirname(full_out_path)) |dirname| {
38 break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? });36 break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? });
src/link/Elf.zig+22-26
...@@ -1026,22 +1026,20 @@ pub fn markDirty(self: *Elf, shdr_index: u16) void {...@@ -1026,22 +1026,20 @@ pub fn markDirty(self: *Elf, shdr_index: u16) void {
1026 }1026 }
1027}1027}
10281028
1029pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {1029pub fn flush(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
1030 const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;1030 const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
1031 if (use_lld) {1031 if (use_lld) {
1032 return self.linkWithLLD(comp, prog_node);1032 return self.linkWithLLD(arena, prog_node);
1033 }1033 }
1034 try self.flushModule(comp, prog_node);1034 try self.flushModule(arena, prog_node);
1035}1035}
10361036
1037pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {1037pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
1038 const tracy = trace(@src());1038 const tracy = trace(@src());
1039 defer tracy.end();1039 defer tracy.end();
10401040
1041 const comp = self.base.comp;
1041 const gpa = comp.gpa;1042 const gpa = comp.gpa;
1042 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
1043 defer arena_allocator.deinit();
1044 const arena = arena_allocator.allocator();
10451043
1046 if (self.llvm_object) |llvm_object| {1044 if (self.llvm_object) |llvm_object| {
1047 try self.base.emitLlvmObject(arena, llvm_object, prog_node);1045 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
...@@ -2349,22 +2347,20 @@ fn scanRelocs(self: *Elf) !void {...@@ -2349,22 +2347,20 @@ fn scanRelocs(self: *Elf) !void {
2349 }2347 }
2350}2348}
23512349
2352fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {2350fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !void {
2353 const tracy = trace(@src());2351 const tracy = trace(@src());
2354 defer tracy.end();2352 defer tracy.end();
23552353
2356 const gpa = self.base.comp.gpa;2354 const comp = self.base.comp;
2357 var arena_allocator = std.heap.ArenaAllocator.init(gpa);2355 const gpa = comp.gpa;
2358 defer arena_allocator.deinit();
2359 const arena = arena_allocator.allocator();
23602356
2361 const directory = self.base.emit.directory; // Just an alias to make it shorter to type.2357 const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
2362 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});2358 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
23632359
2364 // If there is no Zig code to compile, then we should skip flushing the output file because it2360 // If there is no Zig code to compile, then we should skip flushing the output file because it
2365 // will not be part of the linker line anyway.2361 // will not be part of the linker line anyway.
2366 const module_obj_path: ?[]const u8 = if (self.base.comp.module != null) blk: {2362 const module_obj_path: ?[]const u8 = if (comp.module != null) blk: {
2367 try self.flushModule(comp, prog_node);2363 try self.flushModule(arena, prog_node);
23682364
2369 if (fs.path.dirname(full_out_path)) |dirname| {2365 if (fs.path.dirname(full_out_path)) |dirname| {
2370 break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? });2366 break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? });
...@@ -2378,15 +2374,15 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2378,15 +2374,15 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2378 sub_prog_node.context.refresh();2374 sub_prog_node.context.refresh();
2379 defer sub_prog_node.end();2375 defer sub_prog_node.end();
23802376
2381 const output_mode = self.base.comp.config.output_mode;2377 const output_mode = comp.config.output_mode;
2382 const is_obj = output_mode == .Obj;2378 const is_obj = output_mode == .Obj;
2383 const is_lib = output_mode == .Lib;2379 const is_lib = output_mode == .Lib;
2384 const link_mode = self.base.comp.config.link_mode;2380 const link_mode = comp.config.link_mode;
2385 const is_dyn_lib = link_mode == .Dynamic and is_lib;2381 const is_dyn_lib = link_mode == .Dynamic and is_lib;
2386 const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;2382 const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;
2387 const have_dynamic_linker = comp.config.link_libc and2383 const have_dynamic_linker = comp.config.link_libc and
2388 link_mode == .Dynamic and is_exe_or_dyn_lib;2384 link_mode == .Dynamic and is_exe_or_dyn_lib;
2389 const target = self.base.comp.root_mod.resolved_target.result;2385 const target = comp.root_mod.resolved_target.result;
2390 const compiler_rt_path: ?[]const u8 = blk: {2386 const compiler_rt_path: ?[]const u8 = blk: {
2391 if (comp.compiler_rt_lib) |x| break :blk x.full_object_path;2387 if (comp.compiler_rt_lib) |x| break :blk x.full_object_path;
2392 if (comp.compiler_rt_obj) |x| break :blk x.full_object_path;2388 if (comp.compiler_rt_obj) |x| break :blk x.full_object_path;
...@@ -2459,8 +2455,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2459,8 +2455,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2459 man.hash.add(self.hash_style);2455 man.hash.add(self.hash_style);
2460 // strip does not need to go into the linker hash because it is part of the hash namespace2456 // strip does not need to go into the linker hash because it is part of the hash namespace
2461 if (comp.config.link_libc) {2457 if (comp.config.link_libc) {
2462 man.hash.add(self.base.comp.libc_installation != null);2458 man.hash.add(comp.libc_installation != null);
2463 if (self.base.comp.libc_installation) |libc_installation| {2459 if (comp.libc_installation) |libc_installation| {
2464 man.hash.addBytes(libc_installation.crt_dir.?);2460 man.hash.addBytes(libc_installation.crt_dir.?);
2465 }2461 }
2466 if (have_dynamic_linker) {2462 if (have_dynamic_linker) {
...@@ -2469,7 +2465,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2469,7 +2465,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2469 }2465 }
2470 man.hash.addOptionalBytes(self.soname);2466 man.hash.addOptionalBytes(self.soname);
2471 man.hash.addOptional(comp.version);2467 man.hash.addOptional(comp.version);
2472 try link.hashAddSystemLibs(&man, self.base.comp.system_libs);2468 try link.hashAddSystemLibs(&man, comp.system_libs);
2473 man.hash.addListOfBytes(comp.force_undefined_symbols.keys());2469 man.hash.addListOfBytes(comp.force_undefined_symbols.keys());
2474 man.hash.add(self.base.allow_shlib_undefined);2470 man.hash.add(self.base.allow_shlib_undefined);
2475 man.hash.add(self.bind_global_refs_locally);2471 man.hash.add(self.bind_global_refs_locally);
...@@ -2743,7 +2739,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2743,7 +2739,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2743 if (self.each_lib_rpath) {2739 if (self.each_lib_rpath) {
2744 var test_path = std.ArrayList(u8).init(arena);2740 var test_path = std.ArrayList(u8).init(arena);
2745 for (self.lib_dirs) |lib_dir_path| {2741 for (self.lib_dirs) |lib_dir_path| {
2746 for (self.base.comp.system_libs.keys()) |link_lib| {2742 for (comp.system_libs.keys()) |link_lib| {
2747 if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))2743 if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
2748 continue;2744 continue;
2749 if ((try rpath_table.fetchPut(lib_dir_path, {})) == null) {2745 if ((try rpath_table.fetchPut(lib_dir_path, {})) == null) {
...@@ -2771,7 +2767,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2771,7 +2767,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2771 }2767 }
27722768
2773 if (comp.config.link_libc) {2769 if (comp.config.link_libc) {
2774 if (self.base.comp.libc_installation) |libc_installation| {2770 if (comp.libc_installation) |libc_installation| {
2775 try argv.append("-L");2771 try argv.append("-L");
2776 try argv.append(libc_installation.crt_dir.?);2772 try argv.append(libc_installation.crt_dir.?);
2777 }2773 }
...@@ -2841,8 +2837,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2841,8 +2837,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
28412837
2842 // Shared libraries.2838 // Shared libraries.
2843 if (is_exe_or_dyn_lib) {2839 if (is_exe_or_dyn_lib) {
2844 const system_libs = self.base.comp.system_libs.keys();2840 const system_libs = comp.system_libs.keys();
2845 const system_libs_values = self.base.comp.system_libs.values();2841 const system_libs_values = comp.system_libs.values();
28462842
2847 // Worst-case, we need an --as-needed argument for every lib, as well2843 // Worst-case, we need an --as-needed argument for every lib, as well
2848 // as one before and one after.2844 // as one before and one after.
...@@ -2890,7 +2886,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2890,7 +2886,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2890 // libc dep2886 // libc dep
2891 comp.link_error_flags.missing_libc = false;2887 comp.link_error_flags.missing_libc = false;
2892 if (comp.config.link_libc) {2888 if (comp.config.link_libc) {
2893 if (self.base.comp.libc_installation != null) {2889 if (comp.libc_installation != null) {
2894 const needs_grouping = link_mode == .Static;2890 const needs_grouping = link_mode == .Static;
2895 if (needs_grouping) try argv.append("--start-group");2891 if (needs_grouping) try argv.append("--start-group");
2896 try argv.appendSlice(target_util.libcFullLinkFlags(target));2892 try argv.appendSlice(target_util.libcFullLinkFlags(target));
...@@ -2939,7 +2935,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2939,7 +2935,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2939 try argv.append("-Bsymbolic");2935 try argv.append("-Bsymbolic");
2940 }2936 }
29412937
2942 if (self.base.comp.verbose_link) {2938 if (comp.verbose_link) {
2943 // Skip over our own name so that the LLD linker name is the first argv item.2939 // Skip over our own name so that the LLD linker name is the first argv item.
2944 Compilation.dump_argv(argv.items[1..]);2940 Compilation.dump_argv(argv.items[1..]);
2945 }2941 }
src/link/MachO.zig+10-11
...@@ -315,13 +315,14 @@ pub fn open(...@@ -315,13 +315,14 @@ pub fn open(
315 return createEmpty(arena, comp, emit, options);315 return createEmpty(arena, comp, emit, options);
316}316}
317317
318pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {318pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
319 const gpa = self.base.comp.gpa;319 const comp = self.base.comp;
320 const output_mode = self.base.comp.config.output_mode;320 const gpa = comp.gpa;
321 const output_mode = comp.config.output_mode;
321322
322 if (output_mode == .Lib and self.base.comp.config.link_mode == .Static) {323 if (output_mode == .Lib and comp.config.link_mode == .Static) {
323 if (build_options.have_llvm) {324 if (build_options.have_llvm) {
324 return self.base.linkAsArchive(comp, prog_node);325 return self.base.linkAsArchive(arena, prog_node);
325 } else {326 } else {
326 try comp.link_errors.ensureUnusedCapacity(gpa, 1);327 try comp.link_errors.ensureUnusedCapacity(gpa, 1);
327 comp.link_errors.appendAssumeCapacity(.{328 comp.link_errors.appendAssumeCapacity(.{
...@@ -332,19 +333,17 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) li...@@ -332,19 +333,17 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) li
332 }333 }
333334
334 switch (self.mode) {335 switch (self.mode) {
335 .zld => return zld.linkWithZld(self, comp, prog_node),336 .zld => return zld.linkWithZld(self, arena, prog_node),
336 .incremental => return self.flushModule(comp, prog_node),337 .incremental => return self.flushModule(arena, prog_node),
337 }338 }
338}339}
339340
340pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {341pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
341 const tracy = trace(@src());342 const tracy = trace(@src());
342 defer tracy.end();343 defer tracy.end();
343344
345 const comp = self.base.comp;
344 const gpa = comp.gpa;346 const gpa = comp.gpa;
345 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
346 defer arena_allocator.deinit();
347 const arena = arena_allocator.allocator();
348347
349 if (self.llvm_object) |llvm_object| {348 if (self.llvm_object) |llvm_object| {
350 try self.base.emitLlvmObject(arena, llvm_object, prog_node);349 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
src/link/MachO/zld.zig+11-14
...@@ -1,27 +1,24 @@...@@ -1,27 +1,24 @@
1pub fn linkWithZld(1pub fn linkWithZld(
2 macho_file: *MachO,2 macho_file: *MachO,
3 comp: *Compilation,3 arena: Allocator,
4 prog_node: *std.Progress.Node,4 prog_node: *std.Progress.Node,
5) link.File.FlushError!void {5) link.File.FlushError!void {
6 const tracy = trace(@src());6 const tracy = trace(@src());
7 defer tracy.end();7 defer tracy.end();
88
9 const gpa = macho_file.base.comp.gpa;9 const comp = macho_file.base.comp;
10 const target = macho_file.base.comp.root_mod.resolved_target.result;10 const gpa = comp.gpa;
11 const target = comp.root_mod.resolved_target.result;
11 const emit = macho_file.base.emit;12 const emit = macho_file.base.emit;
1213
13 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
14 defer arena_allocator.deinit();
15 const arena = arena_allocator.allocator();
16
17 const directory = emit.directory; // Just an alias to make it shorter to type.14 const directory = emit.directory; // Just an alias to make it shorter to type.
18 const full_out_path = try directory.join(arena, &[_][]const u8{emit.sub_path});15 const full_out_path = try directory.join(arena, &[_][]const u8{emit.sub_path});
19 const opt_zcu = macho_file.base.comp.module;16 const opt_zcu = comp.module;
2017
21 // If there is no Zig code to compile, then we should skip flushing the output file because it18 // If there is no Zig code to compile, then we should skip flushing the output file because it
22 // will not be part of the linker line anyway.19 // will not be part of the linker line anyway.
23 const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {20 const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {
24 try macho_file.flushModule(comp, prog_node);21 try macho_file.flushModule(arena, prog_node);
2522
26 if (fs.path.dirname(full_out_path)) |dirname| {23 if (fs.path.dirname(full_out_path)) |dirname| {
27 break :blk try fs.path.join(arena, &.{ dirname, macho_file.base.zcu_object_sub_path.? });24 break :blk try fs.path.join(arena, &.{ dirname, macho_file.base.zcu_object_sub_path.? });
...@@ -35,8 +32,8 @@ pub fn linkWithZld(...@@ -35,8 +32,8 @@ pub fn linkWithZld(
35 sub_prog_node.context.refresh();32 sub_prog_node.context.refresh();
36 defer sub_prog_node.end();33 defer sub_prog_node.end();
3734
38 const output_mode = macho_file.base.comp.config.output_mode;35 const output_mode = comp.config.output_mode;
39 const link_mode = macho_file.base.comp.config.link_mode;36 const link_mode = comp.config.link_mode;
40 const cpu_arch = target.cpu.arch;37 const cpu_arch = target.cpu.arch;
41 const is_lib = output_mode == .Lib;38 const is_lib = output_mode == .Lib;
42 const is_dyn_lib = link_mode == .Dynamic and is_lib;39 const is_dyn_lib = link_mode == .Dynamic and is_lib;
...@@ -50,7 +47,7 @@ pub fn linkWithZld(...@@ -50,7 +47,7 @@ pub fn linkWithZld(
5047
51 var digest: [Cache.hex_digest_len]u8 = undefined;48 var digest: [Cache.hex_digest_len]u8 = undefined;
5249
53 const objects = macho_file.base.comp.objects;50 const objects = comp.objects;
5451
55 if (!macho_file.base.disable_lld_caching) {52 if (!macho_file.base.disable_lld_caching) {
56 man = comp.cache_parent.obtain();53 man = comp.cache_parent.obtain();
...@@ -76,7 +73,7 @@ pub fn linkWithZld(...@@ -76,7 +73,7 @@ pub fn linkWithZld(
76 man.hash.add(macho_file.headerpad_max_install_names);73 man.hash.add(macho_file.headerpad_max_install_names);
77 man.hash.add(macho_file.base.gc_sections);74 man.hash.add(macho_file.base.gc_sections);
78 man.hash.add(macho_file.dead_strip_dylibs);75 man.hash.add(macho_file.dead_strip_dylibs);
79 man.hash.add(macho_file.base.comp.root_mod.strip);76 man.hash.add(comp.root_mod.strip);
80 try MachO.hashAddFrameworks(&man, macho_file.frameworks);77 try MachO.hashAddFrameworks(&man, macho_file.frameworks);
81 man.hash.addListOfBytes(macho_file.base.rpath_list);78 man.hash.addListOfBytes(macho_file.base.rpath_list);
82 if (is_dyn_lib) {79 if (is_dyn_lib) {
...@@ -406,7 +403,7 @@ pub fn linkWithZld(...@@ -406,7 +403,7 @@ pub fn linkWithZld(
406 try macho_file.createDyldPrivateAtom();403 try macho_file.createDyldPrivateAtom();
407 try macho_file.createTentativeDefAtoms();404 try macho_file.createTentativeDefAtoms();
408405
409 if (macho_file.base.comp.config.output_mode == .Exe) {406 if (comp.config.output_mode == .Exe) {
410 const global = macho_file.getEntryPoint().?;407 const global = macho_file.getEntryPoint().?;
411 if (macho_file.getSymbol(global).undf()) {408 if (macho_file.getSymbol(global).undf()) {
412 // We do one additional check here in case the entry point was found in one of the dylibs.409 // We do one additional check here in case the entry point was found in one of the dylibs.
src/link/NvPtx.zig+4-4
...@@ -106,18 +106,18 @@ pub fn freeDecl(self: *NvPtx, decl_index: InternPool.DeclIndex) void {...@@ -106,18 +106,18 @@ pub fn freeDecl(self: *NvPtx, decl_index: InternPool.DeclIndex) void {
106 return self.llvm_object.freeDecl(decl_index);106 return self.llvm_object.freeDecl(decl_index);
107}107}
108108
109pub fn flush(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {109pub fn flush(self: *NvPtx, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
110 return self.flushModule(comp, prog_node);110 return self.flushModule(arena, prog_node);
111}111}
112112
113pub fn flushModule(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {113pub fn flushModule(self: *NvPtx, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
114 if (build_options.skip_non_native)114 if (build_options.skip_non_native)
115 @panic("Attempted to compile for architecture that was disabled by build configuration");115 @panic("Attempted to compile for architecture that was disabled by build configuration");
116116
117 // The code that was here before mutated the Compilation's file emission mechanism.117 // The code that was here before mutated the Compilation's file emission mechanism.
118 // That's not supposed to happen in flushModule, so I deleted the code.118 // That's not supposed to happen in flushModule, so I deleted the code.
119 _ = arena;
119 _ = self;120 _ = self;
120 _ = comp;
121 _ = prog_node;121 _ = prog_node;
122 @panic("TODO: rewrite the NvPtx.flushModule function");122 @panic("TODO: rewrite the NvPtx.flushModule function");
123}123}
src/link/Plan9.zig+8-4
...@@ -608,8 +608,9 @@ fn allocateGotIndex(self: *Plan9) usize {...@@ -608,8 +608,9 @@ fn allocateGotIndex(self: *Plan9) usize {
608 }608 }
609}609}
610610
611pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {611pub fn flush(self: *Plan9, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
612 const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;612 const comp = self.base.comp;
613 const use_lld = build_options.have_llvm and comp.config.use_lld;
613 assert(!use_lld);614 assert(!use_lld);
614615
615 switch (link.File.effectiveOutputMode(use_lld, comp.config.output_mode)) {616 switch (link.File.effectiveOutputMode(use_lld, comp.config.output_mode)) {
...@@ -618,7 +619,7 @@ pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) li...@@ -618,7 +619,7 @@ pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) li
618 .Obj => return error.TODOImplementPlan9Objs,619 .Obj => return error.TODOImplementPlan9Objs,
619 .Lib => return error.TODOImplementWritingLibFiles,620 .Lib => return error.TODOImplementWritingLibFiles,
620 }621 }
621 return self.flushModule(comp, prog_node);622 return self.flushModule(arena, prog_node);
622}623}
623624
624pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {625pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {
...@@ -666,11 +667,14 @@ fn atomCount(self: *Plan9) usize {...@@ -666,11 +667,14 @@ fn atomCount(self: *Plan9) usize {
666 return data_decl_count + fn_decl_count + unnamed_const_count + lazy_atom_count + extern_atom_count + anon_atom_count;667 return data_decl_count + fn_decl_count + unnamed_const_count + lazy_atom_count + extern_atom_count + anon_atom_count;
667}668}
668669
669pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {670pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
670 if (build_options.skip_non_native and builtin.object_format != .plan9) {671 if (build_options.skip_non_native and builtin.object_format != .plan9) {
671 @panic("Attempted to compile for object format that was disabled by build configuration");672 @panic("Attempted to compile for object format that was disabled by build configuration");
672 }673 }
673674
675 _ = arena; // Has the same lifetime as the call to Compilation.update.
676
677 const comp = self.base.comp;
674 const gpa = comp.gpa;678 const gpa = comp.gpa;
675 const target = comp.root_mod.resolved_target.result;679 const target = comp.root_mod.resolved_target.result;
676680
src/link/SpirV.zig+6-3
...@@ -173,15 +173,17 @@ pub fn freeDecl(self: *SpirV, decl_index: InternPool.DeclIndex) void {...@@ -173,15 +173,17 @@ pub fn freeDecl(self: *SpirV, decl_index: InternPool.DeclIndex) void {
173 _ = decl_index;173 _ = decl_index;
174}174}
175175
176pub fn flush(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {176pub fn flush(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
177 return self.flushModule(comp, prog_node);177 return self.flushModule(arena, prog_node);
178}178}
179179
180pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {180pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
181 if (build_options.skip_non_native) {181 if (build_options.skip_non_native) {
182 @panic("Attempted to compile for architecture that was disabled by build configuration");182 @panic("Attempted to compile for architecture that was disabled by build configuration");
183 }183 }
184184
185 _ = arena; // Has the same lifetime as the call to Compilation.update.
186
185 const tracy = trace(@src());187 const tracy = trace(@src());
186 defer tracy.end();188 defer tracy.end();
187189
...@@ -191,6 +193,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No...@@ -191,6 +193,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
191193
192 const spv = &self.object.spv;194 const spv = &self.object.spv;
193195
196 const comp = self.base.comp;
194 const gpa = comp.gpa;197 const gpa = comp.gpa;
195 const target = comp.getTarget();198 const target = comp.getTarget();
196199
src/link/Wasm.zig+13-23
...@@ -3480,33 +3480,29 @@ fn resetState(wasm: *Wasm) void {...@@ -3480,33 +3480,29 @@ fn resetState(wasm: *Wasm) void {
3480 wasm.debug_pubtypes_index = null;3480 wasm.debug_pubtypes_index = null;
3481}3481}
34823482
3483pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {3483pub fn flush(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
3484 const comp = wasm.base.comp;
3484 const use_lld = build_options.have_llvm and comp.config.use_lld;3485 const use_lld = build_options.have_llvm and comp.config.use_lld;
3485 const use_llvm = comp.config.use_llvm;3486 const use_llvm = comp.config.use_llvm;
34863487
3487 if (use_lld) {3488 if (use_lld) {
3488 return wasm.linkWithLLD(comp, prog_node);3489 return wasm.linkWithLLD(arena, prog_node);
3489 } else if (use_llvm) {3490 } else if (use_llvm) {
3490 return wasm.linkWithZld(comp, prog_node);3491 return wasm.linkWithZld(arena, prog_node);
3491 } else {3492 } else {
3492 return wasm.flushModule(comp, prog_node);3493 return wasm.flushModule(arena, prog_node);
3493 }3494 }
3494}3495}
34953496
3496/// Uses the in-house linker to link one or multiple object -and archive files into a WebAssembly binary.3497/// Uses the in-house linker to link one or multiple object -and archive files into a WebAssembly binary.
3497fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {3498fn linkWithZld(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
3498 const tracy = trace(@src());3499 const tracy = trace(@src());
3499 defer tracy.end();3500 defer tracy.end();
35003501
3501 const gpa = comp.gpa;3502 const comp = wasm.base.comp;
3502 const shared_memory = comp.config.shared_memory;3503 const shared_memory = comp.config.shared_memory;
3503 const import_memory = comp.config.import_memory;3504 const import_memory = comp.config.import_memory;
35043505
3505 // Used for all temporary memory allocated during flushin
3506 var arena_instance = std.heap.ArenaAllocator.init(gpa);
3507 defer arena_instance.deinit();
3508 const arena = arena_instance.allocator();
3509
3510 const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.3506 const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.
3511 const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});3507 const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});
3512 const opt_zcu = comp.module;3508 const opt_zcu = comp.module;
...@@ -3516,7 +3512,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l...@@ -3516,7 +3512,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
3516 // will not be part of the linker line anyway.3512 // will not be part of the linker line anyway.
3517 const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {3513 const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {
3518 assert(use_llvm); // `linkWithZld` should never be called when the Wasm backend is used3514 assert(use_llvm); // `linkWithZld` should never be called when the Wasm backend is used
3519 try wasm.flushModule(comp, prog_node);3515 try wasm.flushModule(arena, prog_node);
35203516
3521 if (fs.path.dirname(full_out_path)) |dirname| {3517 if (fs.path.dirname(full_out_path)) |dirname| {
3522 break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });3518 break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });
...@@ -3708,15 +3704,11 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l...@@ -3708,15 +3704,11 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
3708 }3704 }
3709}3705}
37103706
3711pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {3707pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
3712 const tracy = trace(@src());3708 const tracy = trace(@src());
3713 defer tracy.end();3709 defer tracy.end();
37143710
3715 const gpa = comp.gpa;3711 const comp = wasm.base.comp;
3716 // Used for all temporary memory allocated during flushin
3717 var arena_instance = std.heap.ArenaAllocator.init(gpa);
3718 defer arena_instance.deinit();
3719 const arena = arena_instance.allocator();
37203712
3721 if (wasm.llvm_object) |llvm_object| {3713 if (wasm.llvm_object) |llvm_object| {
3722 try wasm.base.emitLlvmObject(arena, llvm_object, prog_node);3714 try wasm.base.emitLlvmObject(arena, llvm_object, prog_node);
...@@ -4589,19 +4581,17 @@ fn emitImport(wasm: *Wasm, writer: anytype, import: types.Import) !void {...@@ -4589,19 +4581,17 @@ fn emitImport(wasm: *Wasm, writer: anytype, import: types.Import) !void {
4589 }4581 }
4590}4582}
45914583
4592fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {4584fn linkWithLLD(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) !void {
4593 const tracy = trace(@src());4585 const tracy = trace(@src());
4594 defer tracy.end();4586 defer tracy.end();
45954587
4588 const comp = wasm.base.comp;
4596 const shared_memory = comp.config.shared_memory;4589 const shared_memory = comp.config.shared_memory;
4597 const export_memory = comp.config.export_memory;4590 const export_memory = comp.config.export_memory;
4598 const import_memory = comp.config.import_memory;4591 const import_memory = comp.config.import_memory;
4599 const target = comp.root_mod.resolved_target.result;4592 const target = comp.root_mod.resolved_target.result;
46004593
4601 const gpa = comp.gpa;4594 const gpa = comp.gpa;
4602 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
4603 defer arena_allocator.deinit();
4604 const arena = arena_allocator.allocator();
46054595
4606 const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.4596 const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.
4607 const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});4597 const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});
...@@ -4609,7 +4599,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4609,7 +4599,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4609 // If there is no Zig code to compile, then we should skip flushing the output file because it4599 // If there is no Zig code to compile, then we should skip flushing the output file because it
4610 // will not be part of the linker line anyway.4600 // will not be part of the linker line anyway.
4611 const module_obj_path: ?[]const u8 = if (comp.module != null) blk: {4601 const module_obj_path: ?[]const u8 = if (comp.module != null) blk: {
4612 try wasm.flushModule(comp, prog_node);4602 try wasm.flushModule(arena, prog_node);
46134603
4614 if (fs.path.dirname(full_out_path)) |dirname| {4604 if (fs.path.dirname(full_out_path)) |dirname| {
4615 break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });4605 break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });