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
23112311fn flush(comp: *Compilation, arena: Allocator, prog_node: *std.Progress.Node) !void {
23122312 if (comp.bin_file) |lf| {
23132313 // 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) {
23152315 error.FlushFailure => {}, // error reported through link_error_flags
23162316 error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr
23172317 else => |e| return e,
src/link.zig+15-14
......@@ -547,19 +547,22 @@ pub const File = struct {
547547
548548 /// Commit pending changes and write headers. Takes into account final output mode
549549 /// 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 {
551552 if (build_options.only_c) {
552553 assert(base.tag == .c);
553 return @fieldParentPtr(C, "base", base).flush(comp, prog_node);
554 return @fieldParentPtr(C, "base", base).flush(arena, prog_node);
554555 }
556 const comp = base.comp;
555557 if (comp.clang_preprocessor_mode == .yes) {
558 const gpa = comp.gpa;
556559 const emit = base.emit;
557560 // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)
558561 // Until then, we do `lld -r -o output.o input.o` even though the output is the same
559562 // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file
560563 // 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});
562 defer comp.gpa.free(full_out_path);
564 const full_out_path = try emit.directory.join(gpa, &[_][]const u8{emit.sub_path});
565 defer gpa.free(full_out_path);
563566 assert(comp.c_object_table.count() == 1);
564567 const the_key = comp.c_object_table.keys()[0];
565568 const cached_pp_file_path = the_key.status.success.object_path;
......@@ -571,25 +574,25 @@ pub const File = struct {
571574 const output_mode = comp.config.output_mode;
572575 const link_mode = comp.config.link_mode;
573576 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);
575578 }
576579 switch (base.tag) {
577580 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);
579582 },
580583 }
581584 }
582585
583586 /// Commit pending changes and write headers. Works based on `effectiveOutputMode`
584587 /// 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 {
586589 switch (base.tag) {
587590 .c => {
588 return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node);
591 return @fieldParentPtr(C, "base", base).flushModule(arena, prog_node);
589592 },
590593 inline else => |tag| {
591594 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);
593596 },
594597 }
595598 }
......@@ -707,14 +710,12 @@ pub const File = struct {
707710 }
708711 }
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 {
711714 const tracy = trace(@src());
712715 defer tracy.end();
713716
717 const comp = base.comp;
714718 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
719720 const directory = base.emit.directory; // Just an alias to make it shorter to type.
720721 const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
......@@ -724,7 +725,7 @@ pub const File = struct {
724725 // If there is no Zig code to compile, then we should skip flushing the output file
725726 // because it will not be part of the linker line anyway.
726727 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
729730 const dirname = fs.path.dirname(full_out_path_z) orelse ".";
730731 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
376376 _ = decl_index;
377377}
378378
379pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void {
380 return self.flushModule(comp, prog_node);
379pub fn flush(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !void {
380 return self.flushModule(arena, prog_node);
381381}
382382
383383fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
......@@ -393,7 +393,9 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
393393 return defines;
394394}
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
397399 const tracy = trace(@src());
398400 defer tracy.end();
399401
......@@ -401,7 +403,8 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
401403 sub_prog_node.activate();
402404 defer sub_prog_node.end();
403405
404 const gpa = self.base.comp.gpa;
406 const comp = self.base.comp;
407 const gpa = comp.gpa;
405408 const module = self.base.comp.module.?;
406409
407410 {
src/link/Coff.zig+8-10
......@@ -1706,28 +1706,26 @@ fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void {
17061706 gop.value_ptr.* = current;
17071707}
17081708
1709pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
1710 const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
1709pub fn flush(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
1710 const comp = self.base.comp;
1711 const use_lld = build_options.have_llvm and comp.config.use_lld;
17111712 if (use_lld) {
1712 return lld.linkWithLLD(self, comp, prog_node);
1713 return lld.linkWithLLD(self, arena, prog_node);
17131714 }
1714 switch (self.base.comp.config.output_mode) {
1715 .Exe, .Obj => return self.flushModule(comp, prog_node),
1715 switch (comp.config.output_mode) {
1716 .Exe, .Obj => return self.flushModule(arena, prog_node),
17161717 .Lib => return error.TODOImplementWritingLibFiles,
17171718 }
17181719}
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 {
17211722 const tracy = trace(@src());
17221723 defer tracy.end();
17231724
1725 const comp = self.base.comp;
17241726 const gpa = comp.gpa;
17251727
17261728 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
17311729 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
17321730 return;
17331731 }
src/link/Coff/lld.zig+3-5
......@@ -17,14 +17,12 @@ const Allocator = mem.Allocator;
1717const Coff = @import("../Coff.zig");
1818const 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 {
2121 const tracy = trace(@src());
2222 defer tracy.end();
2323
24 const comp = self.base.comp;
2425 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
2927 const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
3028 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
3230 // If there is no Zig code to compile, then we should skip flushing the output file because it
3331 // will not be part of the linker line anyway.
3432 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
3735 if (fs.path.dirname(full_out_path)) |dirname| {
3836 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 {
10261026 }
10271027}
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 {
10301030 const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
10311031 if (use_lld) {
1032 return self.linkWithLLD(comp, prog_node);
1032 return self.linkWithLLD(arena, prog_node);
10331033 }
1034 try self.flushModule(comp, prog_node);
1034 try self.flushModule(arena, prog_node);
10351035}
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 {
10381038 const tracy = trace(@src());
10391039 defer tracy.end();
10401040
1041 const comp = self.base.comp;
10411042 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
10461044 if (self.llvm_object) |llvm_object| {
10471045 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
......@@ -2349,22 +2347,20 @@ fn scanRelocs(self: *Elf) !void {
23492347 }
23502348}
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 {
23532351 const tracy = trace(@src());
23542352 defer tracy.end();
23552353
2356 const gpa = self.base.comp.gpa;
2357 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
2358 defer arena_allocator.deinit();
2359 const arena = arena_allocator.allocator();
2354 const comp = self.base.comp;
2355 const gpa = comp.gpa;
23602356
23612357 const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
23622358 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
23632359
23642360 // If there is no Zig code to compile, then we should skip flushing the output file because it
23652361 // will not be part of the linker line anyway.
2366 const module_obj_path: ?[]const u8 = if (self.base.comp.module != null) blk: {
2367 try self.flushModule(comp, prog_node);
2362 const module_obj_path: ?[]const u8 = if (comp.module != null) blk: {
2363 try self.flushModule(arena, prog_node);
23682364
23692365 if (fs.path.dirname(full_out_path)) |dirname| {
23702366 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
23782374 sub_prog_node.context.refresh();
23792375 defer sub_prog_node.end();
23802376
2381 const output_mode = self.base.comp.config.output_mode;
2377 const output_mode = comp.config.output_mode;
23822378 const is_obj = output_mode == .Obj;
23832379 const is_lib = output_mode == .Lib;
2384 const link_mode = self.base.comp.config.link_mode;
2380 const link_mode = comp.config.link_mode;
23852381 const is_dyn_lib = link_mode == .Dynamic and is_lib;
23862382 const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;
23872383 const have_dynamic_linker = comp.config.link_libc and
23882384 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;
23902386 const compiler_rt_path: ?[]const u8 = blk: {
23912387 if (comp.compiler_rt_lib) |x| break :blk x.full_object_path;
23922388 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
24592455 man.hash.add(self.hash_style);
24602456 // strip does not need to go into the linker hash because it is part of the hash namespace
24612457 if (comp.config.link_libc) {
2462 man.hash.add(self.base.comp.libc_installation != null);
2463 if (self.base.comp.libc_installation) |libc_installation| {
2458 man.hash.add(comp.libc_installation != null);
2459 if (comp.libc_installation) |libc_installation| {
24642460 man.hash.addBytes(libc_installation.crt_dir.?);
24652461 }
24662462 if (have_dynamic_linker) {
......@@ -2469,7 +2465,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
24692465 }
24702466 man.hash.addOptionalBytes(self.soname);
24712467 man.hash.addOptional(comp.version);
2472 try link.hashAddSystemLibs(&man, self.base.comp.system_libs);
2468 try link.hashAddSystemLibs(&man, comp.system_libs);
24732469 man.hash.addListOfBytes(comp.force_undefined_symbols.keys());
24742470 man.hash.add(self.base.allow_shlib_undefined);
24752471 man.hash.add(self.bind_global_refs_locally);
......@@ -2743,7 +2739,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
27432739 if (self.each_lib_rpath) {
27442740 var test_path = std.ArrayList(u8).init(arena);
27452741 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| {
27472743 if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
27482744 continue;
27492745 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
27712767 }
27722768
27732769 if (comp.config.link_libc) {
2774 if (self.base.comp.libc_installation) |libc_installation| {
2770 if (comp.libc_installation) |libc_installation| {
27752771 try argv.append("-L");
27762772 try argv.append(libc_installation.crt_dir.?);
27772773 }
......@@ -2841,8 +2837,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
28412837
28422838 // Shared libraries.
28432839 if (is_exe_or_dyn_lib) {
2844 const system_libs = self.base.comp.system_libs.keys();
2845 const system_libs_values = self.base.comp.system_libs.values();
2840 const system_libs = comp.system_libs.keys();
2841 const system_libs_values = comp.system_libs.values();
28462842
28472843 // Worst-case, we need an --as-needed argument for every lib, as well
28482844 // as one before and one after.
......@@ -2890,7 +2886,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
28902886 // libc dep
28912887 comp.link_error_flags.missing_libc = false;
28922888 if (comp.config.link_libc) {
2893 if (self.base.comp.libc_installation != null) {
2889 if (comp.libc_installation != null) {
28942890 const needs_grouping = link_mode == .Static;
28952891 if (needs_grouping) try argv.append("--start-group");
28962892 try argv.appendSlice(target_util.libcFullLinkFlags(target));
......@@ -2939,7 +2935,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
29392935 try argv.append("-Bsymbolic");
29402936 }
29412937
2942 if (self.base.comp.verbose_link) {
2938 if (comp.verbose_link) {
29432939 // Skip over our own name so that the LLD linker name is the first argv item.
29442940 Compilation.dump_argv(argv.items[1..]);
29452941 }
src/link/MachO.zig+10-11
......@@ -315,13 +315,14 @@ pub fn open(
315315 return createEmpty(arena, comp, emit, options);
316316}
317317
318pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
319 const gpa = self.base.comp.gpa;
320 const output_mode = self.base.comp.config.output_mode;
318pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
319 const comp = self.base.comp;
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) {
323324 if (build_options.have_llvm) {
324 return self.base.linkAsArchive(comp, prog_node);
325 return self.base.linkAsArchive(arena, prog_node);
325326 } else {
326327 try comp.link_errors.ensureUnusedCapacity(gpa, 1);
327328 comp.link_errors.appendAssumeCapacity(.{
......@@ -332,19 +333,17 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) li
332333 }
333334
334335 switch (self.mode) {
335 .zld => return zld.linkWithZld(self, comp, prog_node),
336 .incremental => return self.flushModule(comp, prog_node),
336 .zld => return zld.linkWithZld(self, arena, prog_node),
337 .incremental => return self.flushModule(arena, prog_node),
337338 }
338339}
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 {
341342 const tracy = trace(@src());
342343 defer tracy.end();
343344
345 const comp = self.base.comp;
344346 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
349348 if (self.llvm_object) |llvm_object| {
350349 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
src/link/MachO/zld.zig+11-14
......@@ -1,27 +1,24 @@
11pub fn linkWithZld(
22 macho_file: *MachO,
3 comp: *Compilation,
3 arena: Allocator,
44 prog_node: *std.Progress.Node,
55) link.File.FlushError!void {
66 const tracy = trace(@src());
77 defer tracy.end();
88
9 const gpa = macho_file.base.comp.gpa;
10 const target = macho_file.base.comp.root_mod.resolved_target.result;
9 const comp = macho_file.base.comp;
10 const gpa = comp.gpa;
11 const target = comp.root_mod.resolved_target.result;
1112 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
1714 const directory = emit.directory; // Just an alias to make it shorter to type.
1815 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
2118 // If there is no Zig code to compile, then we should skip flushing the output file because it
2219 // will not be part of the linker line anyway.
2320 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
2623 if (fs.path.dirname(full_out_path)) |dirname| {
2724 break :blk try fs.path.join(arena, &.{ dirname, macho_file.base.zcu_object_sub_path.? });
......@@ -35,8 +32,8 @@ pub fn linkWithZld(
3532 sub_prog_node.context.refresh();
3633 defer sub_prog_node.end();
3734
38 const output_mode = macho_file.base.comp.config.output_mode;
39 const link_mode = macho_file.base.comp.config.link_mode;
35 const output_mode = comp.config.output_mode;
36 const link_mode = comp.config.link_mode;
4037 const cpu_arch = target.cpu.arch;
4138 const is_lib = output_mode == .Lib;
4239 const is_dyn_lib = link_mode == .Dynamic and is_lib;
......@@ -50,7 +47,7 @@ pub fn linkWithZld(
5047
5148 var digest: [Cache.hex_digest_len]u8 = undefined;
5249
53 const objects = macho_file.base.comp.objects;
50 const objects = comp.objects;
5451
5552 if (!macho_file.base.disable_lld_caching) {
5653 man = comp.cache_parent.obtain();
......@@ -76,7 +73,7 @@ pub fn linkWithZld(
7673 man.hash.add(macho_file.headerpad_max_install_names);
7774 man.hash.add(macho_file.base.gc_sections);
7875 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);
8077 try MachO.hashAddFrameworks(&man, macho_file.frameworks);
8178 man.hash.addListOfBytes(macho_file.base.rpath_list);
8279 if (is_dyn_lib) {
......@@ -406,7 +403,7 @@ pub fn linkWithZld(
406403 try macho_file.createDyldPrivateAtom();
407404 try macho_file.createTentativeDefAtoms();
408405
409 if (macho_file.base.comp.config.output_mode == .Exe) {
406 if (comp.config.output_mode == .Exe) {
410407 const global = macho_file.getEntryPoint().?;
411408 if (macho_file.getSymbol(global).undf()) {
412409 // 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 {
106106 return self.llvm_object.freeDecl(decl_index);
107107}
108108
109pub fn flush(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
110 return self.flushModule(comp, prog_node);
109pub fn flush(self: *NvPtx, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
110 return self.flushModule(arena, prog_node);
111111}
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 {
114114 if (build_options.skip_non_native)
115115 @panic("Attempted to compile for architecture that was disabled by build configuration");
116116
117117 // The code that was here before mutated the Compilation's file emission mechanism.
118118 // That's not supposed to happen in flushModule, so I deleted the code.
119 _ = arena;
119120 _ = self;
120 _ = comp;
121121 _ = prog_node;
122122 @panic("TODO: rewrite the NvPtx.flushModule function");
123123}
src/link/Plan9.zig+8-4
......@@ -608,8 +608,9 @@ fn allocateGotIndex(self: *Plan9) usize {
608608 }
609609}
610610
611pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
612 const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
611pub fn flush(self: *Plan9, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
612 const comp = self.base.comp;
613 const use_lld = build_options.have_llvm and comp.config.use_lld;
613614 assert(!use_lld);
614615
615616 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
618619 .Obj => return error.TODOImplementPlan9Objs,
619620 .Lib => return error.TODOImplementWritingLibFiles,
620621 }
621 return self.flushModule(comp, prog_node);
622 return self.flushModule(arena, prog_node);
622623}
623624
624625pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {
......@@ -666,11 +667,14 @@ fn atomCount(self: *Plan9) usize {
666667 return data_decl_count + fn_decl_count + unnamed_const_count + lazy_atom_count + extern_atom_count + anon_atom_count;
667668}
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 {
670671 if (build_options.skip_non_native and builtin.object_format != .plan9) {
671672 @panic("Attempted to compile for object format that was disabled by build configuration");
672673 }
673674
675 _ = arena; // Has the same lifetime as the call to Compilation.update.
676
677 const comp = self.base.comp;
674678 const gpa = comp.gpa;
675679 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 {
173173 _ = decl_index;
174174}
175175
176pub fn flush(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
177 return self.flushModule(comp, prog_node);
176pub fn flush(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
177 return self.flushModule(arena, prog_node);
178178}
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 {
181181 if (build_options.skip_non_native) {
182182 @panic("Attempted to compile for architecture that was disabled by build configuration");
183183 }
184184
185 _ = arena; // Has the same lifetime as the call to Compilation.update.
186
185187 const tracy = trace(@src());
186188 defer tracy.end();
187189
......@@ -191,6 +193,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
191193
192194 const spv = &self.object.spv;
193195
196 const comp = self.base.comp;
194197 const gpa = comp.gpa;
195198 const target = comp.getTarget();
196199
src/link/Wasm.zig+13-23
......@@ -3480,33 +3480,29 @@ fn resetState(wasm: *Wasm) void {
34803480 wasm.debug_pubtypes_index = null;
34813481}
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;
34843485 const use_lld = build_options.have_llvm and comp.config.use_lld;
34853486 const use_llvm = comp.config.use_llvm;
34863487
34873488 if (use_lld) {
3488 return wasm.linkWithLLD(comp, prog_node);
3489 return wasm.linkWithLLD(arena, prog_node);
34893490 } else if (use_llvm) {
3490 return wasm.linkWithZld(comp, prog_node);
3491 return wasm.linkWithZld(arena, prog_node);
34913492 } else {
3492 return wasm.flushModule(comp, prog_node);
3493 return wasm.flushModule(arena, prog_node);
34933494 }
34943495}
34953496
34963497/// 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 {
34983499 const tracy = trace(@src());
34993500 defer tracy.end();
35003501
3501 const gpa = comp.gpa;
3502 const comp = wasm.base.comp;
35023503 const shared_memory = comp.config.shared_memory;
35033504 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
35103506 const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.
35113507 const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});
35123508 const opt_zcu = comp.module;
......@@ -3516,7 +3512,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
35163512 // will not be part of the linker line anyway.
35173513 const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {
35183514 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
35213517 if (fs.path.dirname(full_out_path)) |dirname| {
35223518 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
37083704 }
37093705}
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 {
37123708 const tracy = trace(@src());
37133709 defer tracy.end();
37143710
3715 const gpa = comp.gpa;
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();
3711 const comp = wasm.base.comp;
37203712
37213713 if (wasm.llvm_object) |llvm_object| {
37223714 try wasm.base.emitLlvmObject(arena, llvm_object, prog_node);
......@@ -4589,19 +4581,17 @@ fn emitImport(wasm: *Wasm, writer: anytype, import: types.Import) !void {
45894581 }
45904582}
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 {
45934585 const tracy = trace(@src());
45944586 defer tracy.end();
45954587
4588 const comp = wasm.base.comp;
45964589 const shared_memory = comp.config.shared_memory;
45974590 const export_memory = comp.config.export_memory;
45984591 const import_memory = comp.config.import_memory;
45994592 const target = comp.root_mod.resolved_target.result;
46004593
46014594 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
46064596 const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.
46074597 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) !
46094599 // If there is no Zig code to compile, then we should skip flushing the output file because it
46104600 // will not be part of the linker line anyway.
46114601 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
46144604 if (fs.path.dirname(full_out_path)) |dirname| {
46154605 break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });