aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-01-01 19:11:57 -0700
committerAndrew Kelley <andrew@ziglang.org>2024-01-01 19:49:08 -0700
commitd5c1e7f7b1381036f7d98c1944607cb0e1c0d4da (patch)
treef78506c79713b855ed8f23426ce78e0e292e13ee /src/link
parenteae6d45cded76dd027569c86a7cdd5bc9039664b (diff)
downloadzig-d5c1e7f7b1381036f7d98c1944607cb0e1c0d4da.tar.gz
zig-d5c1e7f7b1381036f7d98c1944607cb0e1c0d4da.zip
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`.
Diffstat (limited to 'src/link')
-rw-r--r--src/link/C.zig11
-rw-r--r--src/link/Coff.zig18
-rw-r--r--src/link/Coff/lld.zig8
-rw-r--r--src/link/Elf.zig48
-rw-r--r--src/link/MachO.zig21
-rw-r--r--src/link/MachO/zld.zig25
-rw-r--r--src/link/NvPtx.zig8
-rw-r--r--src/link/Plan9.zig12
-rw-r--r--src/link/SpirV.zig9
-rw-r--r--src/link/Wasm.zig36
10 files changed, 92 insertions, 104 deletions
diff --git a/src/link/C.zig b/src/link/C.zig
index 958ce12a06..68facb374b 100644
--- a/src/link/C.zig
+++ b/src/link/C.zig
@@ -376,8 +376,8 @@ pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: InternPool.De
_ = decl_index;
}
-pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void {
- return self.flushModule(comp, prog_node);
+pub fn flush(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !void {
+ return self.flushModule(arena, prog_node);
}
fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
@@ -393,7 +393,9 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
return defines;
}
-pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !void {
+pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !void {
+ _ = arena; // Has the same lifetime as the call to Compilation.update.
+
const tracy = trace(@src());
defer tracy.end();
@@ -401,7 +403,8 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
sub_prog_node.activate();
defer sub_prog_node.end();
- const gpa = self.base.comp.gpa;
+ const comp = self.base.comp;
+ const gpa = comp.gpa;
const module = self.base.comp.module.?;
{
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index 7c95c3803e..7d825ef4d1 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -1706,28 +1706,26 @@ fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void {
gop.value_ptr.* = current;
}
-pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
- const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
+pub fn flush(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
+ const comp = self.base.comp;
+ const use_lld = build_options.have_llvm and comp.config.use_lld;
if (use_lld) {
- return lld.linkWithLLD(self, comp, prog_node);
+ return lld.linkWithLLD(self, arena, prog_node);
}
- switch (self.base.comp.config.output_mode) {
- .Exe, .Obj => return self.flushModule(comp, prog_node),
+ switch (comp.config.output_mode) {
+ .Exe, .Obj => return self.flushModule(arena, prog_node),
.Lib => return error.TODOImplementWritingLibFiles,
}
}
-pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
+pub fn flushModule(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
const tracy = trace(@src());
defer tracy.end();
+ const comp = self.base.comp;
const gpa = comp.gpa;
if (self.llvm_object) |llvm_object| {
- var arena_allocator = std.heap.ArenaAllocator.init(gpa);
- defer arena_allocator.deinit();
- const arena = arena_allocator.allocator();
-
try self.base.emitLlvmObject(arena, llvm_object, prog_node);
return;
}
diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig
index 3a833c40ae..914be5a443 100644
--- a/src/link/Coff/lld.zig
+++ b/src/link/Coff/lld.zig
@@ -17,14 +17,12 @@ const Allocator = mem.Allocator;
const Coff = @import("../Coff.zig");
const Compilation = @import("../../Compilation.zig");
-pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {
+pub fn linkWithLLD(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();
+ const comp = self.base.comp;
const gpa = comp.gpa;
- var arena_allocator = std.heap.ArenaAllocator.init(gpa);
- defer arena_allocator.deinit();
- const arena = arena_allocator.allocator();
const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
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
// If there is no Zig code to compile, then we should skip flushing the output file because it
// will not be part of the linker line anyway.
const module_obj_path: ?[]const u8 = if (comp.module != null) blk: {
- try self.flushModule(comp, prog_node);
+ try self.flushModule(arena, prog_node);
if (fs.path.dirname(full_out_path)) |dirname| {
break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? });
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index a74b4b5ae6..2f1d5703f9 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1026,22 +1026,20 @@ pub fn markDirty(self: *Elf, shdr_index: u16) void {
}
}
-pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
+pub fn flush(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
if (use_lld) {
- return self.linkWithLLD(comp, prog_node);
+ return self.linkWithLLD(arena, prog_node);
}
- try self.flushModule(comp, prog_node);
+ try self.flushModule(arena, prog_node);
}
-pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
+pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
const tracy = trace(@src());
defer tracy.end();
+ const comp = self.base.comp;
const gpa = comp.gpa;
- var arena_allocator = std.heap.ArenaAllocator.init(gpa);
- defer arena_allocator.deinit();
- const arena = arena_allocator.allocator();
if (self.llvm_object) |llvm_object| {
try self.base.emitLlvmObject(arena, llvm_object, prog_node);
@@ -2349,22 +2347,20 @@ fn scanRelocs(self: *Elf) !void {
}
}
-fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
+fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();
- const gpa = self.base.comp.gpa;
- var arena_allocator = std.heap.ArenaAllocator.init(gpa);
- defer arena_allocator.deinit();
- const arena = arena_allocator.allocator();
+ const comp = self.base.comp;
+ const gpa = comp.gpa;
const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
// If there is no Zig code to compile, then we should skip flushing the output file because it
// will not be part of the linker line anyway.
- const module_obj_path: ?[]const u8 = if (self.base.comp.module != null) blk: {
- try self.flushModule(comp, prog_node);
+ const module_obj_path: ?[]const u8 = if (comp.module != null) blk: {
+ try self.flushModule(arena, prog_node);
if (fs.path.dirname(full_out_path)) |dirname| {
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
sub_prog_node.context.refresh();
defer sub_prog_node.end();
- const output_mode = self.base.comp.config.output_mode;
+ const output_mode = comp.config.output_mode;
const is_obj = output_mode == .Obj;
const is_lib = output_mode == .Lib;
- const link_mode = self.base.comp.config.link_mode;
+ const link_mode = comp.config.link_mode;
const is_dyn_lib = link_mode == .Dynamic and is_lib;
const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;
const have_dynamic_linker = comp.config.link_libc and
link_mode == .Dynamic and is_exe_or_dyn_lib;
- const target = self.base.comp.root_mod.resolved_target.result;
+ const target = comp.root_mod.resolved_target.result;
const compiler_rt_path: ?[]const u8 = blk: {
if (comp.compiler_rt_lib) |x| break :blk x.full_object_path;
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
man.hash.add(self.hash_style);
// strip does not need to go into the linker hash because it is part of the hash namespace
if (comp.config.link_libc) {
- man.hash.add(self.base.comp.libc_installation != null);
- if (self.base.comp.libc_installation) |libc_installation| {
+ man.hash.add(comp.libc_installation != null);
+ if (comp.libc_installation) |libc_installation| {
man.hash.addBytes(libc_installation.crt_dir.?);
}
if (have_dynamic_linker) {
@@ -2469,7 +2465,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
}
man.hash.addOptionalBytes(self.soname);
man.hash.addOptional(comp.version);
- try link.hashAddSystemLibs(&man, self.base.comp.system_libs);
+ try link.hashAddSystemLibs(&man, comp.system_libs);
man.hash.addListOfBytes(comp.force_undefined_symbols.keys());
man.hash.add(self.base.allow_shlib_undefined);
man.hash.add(self.bind_global_refs_locally);
@@ -2743,7 +2739,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
if (self.each_lib_rpath) {
var test_path = std.ArrayList(u8).init(arena);
for (self.lib_dirs) |lib_dir_path| {
- for (self.base.comp.system_libs.keys()) |link_lib| {
+ for (comp.system_libs.keys()) |link_lib| {
if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
continue;
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
}
if (comp.config.link_libc) {
- if (self.base.comp.libc_installation) |libc_installation| {
+ if (comp.libc_installation) |libc_installation| {
try argv.append("-L");
try argv.append(libc_installation.crt_dir.?);
}
@@ -2841,8 +2837,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
// Shared libraries.
if (is_exe_or_dyn_lib) {
- const system_libs = self.base.comp.system_libs.keys();
- const system_libs_values = self.base.comp.system_libs.values();
+ const system_libs = comp.system_libs.keys();
+ const system_libs_values = comp.system_libs.values();
// Worst-case, we need an --as-needed argument for every lib, as well
// as one before and one after.
@@ -2890,7 +2886,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
// libc dep
comp.link_error_flags.missing_libc = false;
if (comp.config.link_libc) {
- if (self.base.comp.libc_installation != null) {
+ if (comp.libc_installation != null) {
const needs_grouping = link_mode == .Static;
if (needs_grouping) try argv.append("--start-group");
try argv.appendSlice(target_util.libcFullLinkFlags(target));
@@ -2939,7 +2935,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
try argv.append("-Bsymbolic");
}
- if (self.base.comp.verbose_link) {
+ if (comp.verbose_link) {
// Skip over our own name so that the LLD linker name is the first argv item.
Compilation.dump_argv(argv.items[1..]);
}
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index c0a259d982..cb26aa0ca3 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -315,13 +315,14 @@ pub fn open(
return createEmpty(arena, comp, emit, options);
}
-pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
- const gpa = self.base.comp.gpa;
- const output_mode = self.base.comp.config.output_mode;
+pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
+ const comp = self.base.comp;
+ const gpa = comp.gpa;
+ const output_mode = comp.config.output_mode;
- if (output_mode == .Lib and self.base.comp.config.link_mode == .Static) {
+ if (output_mode == .Lib and comp.config.link_mode == .Static) {
if (build_options.have_llvm) {
- return self.base.linkAsArchive(comp, prog_node);
+ return self.base.linkAsArchive(arena, prog_node);
} else {
try comp.link_errors.ensureUnusedCapacity(gpa, 1);
comp.link_errors.appendAssumeCapacity(.{
@@ -332,19 +333,17 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) li
}
switch (self.mode) {
- .zld => return zld.linkWithZld(self, comp, prog_node),
- .incremental => return self.flushModule(comp, prog_node),
+ .zld => return zld.linkWithZld(self, arena, prog_node),
+ .incremental => return self.flushModule(arena, prog_node),
}
}
-pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
+pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
const tracy = trace(@src());
defer tracy.end();
+ const comp = self.base.comp;
const gpa = comp.gpa;
- var arena_allocator = std.heap.ArenaAllocator.init(gpa);
- defer arena_allocator.deinit();
- const arena = arena_allocator.allocator();
if (self.llvm_object) |llvm_object| {
try self.base.emitLlvmObject(arena, llvm_object, prog_node);
diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig
index 81b10c59d9..b266bfeb47 100644
--- a/src/link/MachO/zld.zig
+++ b/src/link/MachO/zld.zig
@@ -1,27 +1,24 @@
pub fn linkWithZld(
macho_file: *MachO,
- comp: *Compilation,
+ arena: Allocator,
prog_node: *std.Progress.Node,
) link.File.FlushError!void {
const tracy = trace(@src());
defer tracy.end();
- const gpa = macho_file.base.comp.gpa;
- const target = macho_file.base.comp.root_mod.resolved_target.result;
+ const comp = macho_file.base.comp;
+ const gpa = comp.gpa;
+ const target = comp.root_mod.resolved_target.result;
const emit = macho_file.base.emit;
- var arena_allocator = std.heap.ArenaAllocator.init(gpa);
- defer arena_allocator.deinit();
- const arena = arena_allocator.allocator();
-
const directory = emit.directory; // Just an alias to make it shorter to type.
const full_out_path = try directory.join(arena, &[_][]const u8{emit.sub_path});
- const opt_zcu = macho_file.base.comp.module;
+ const opt_zcu = comp.module;
// If there is no Zig code to compile, then we should skip flushing the output file because it
// will not be part of the linker line anyway.
const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {
- try macho_file.flushModule(comp, prog_node);
+ try macho_file.flushModule(arena, prog_node);
if (fs.path.dirname(full_out_path)) |dirname| {
break :blk try fs.path.join(arena, &.{ dirname, macho_file.base.zcu_object_sub_path.? });
@@ -35,8 +32,8 @@ pub fn linkWithZld(
sub_prog_node.context.refresh();
defer sub_prog_node.end();
- const output_mode = macho_file.base.comp.config.output_mode;
- const link_mode = macho_file.base.comp.config.link_mode;
+ const output_mode = comp.config.output_mode;
+ const link_mode = comp.config.link_mode;
const cpu_arch = target.cpu.arch;
const is_lib = output_mode == .Lib;
const is_dyn_lib = link_mode == .Dynamic and is_lib;
@@ -50,7 +47,7 @@ pub fn linkWithZld(
var digest: [Cache.hex_digest_len]u8 = undefined;
- const objects = macho_file.base.comp.objects;
+ const objects = comp.objects;
if (!macho_file.base.disable_lld_caching) {
man = comp.cache_parent.obtain();
@@ -76,7 +73,7 @@ pub fn linkWithZld(
man.hash.add(macho_file.headerpad_max_install_names);
man.hash.add(macho_file.base.gc_sections);
man.hash.add(macho_file.dead_strip_dylibs);
- man.hash.add(macho_file.base.comp.root_mod.strip);
+ man.hash.add(comp.root_mod.strip);
try MachO.hashAddFrameworks(&man, macho_file.frameworks);
man.hash.addListOfBytes(macho_file.base.rpath_list);
if (is_dyn_lib) {
@@ -406,7 +403,7 @@ pub fn linkWithZld(
try macho_file.createDyldPrivateAtom();
try macho_file.createTentativeDefAtoms();
- if (macho_file.base.comp.config.output_mode == .Exe) {
+ if (comp.config.output_mode == .Exe) {
const global = macho_file.getEntryPoint().?;
if (macho_file.getSymbol(global).undf()) {
// We do one additional check here in case the entry point was found in one of the dylibs.
diff --git a/src/link/NvPtx.zig b/src/link/NvPtx.zig
index 1f5af5b86e..111b59fc3b 100644
--- a/src/link/NvPtx.zig
+++ b/src/link/NvPtx.zig
@@ -106,18 +106,18 @@ pub fn freeDecl(self: *NvPtx, decl_index: InternPool.DeclIndex) void {
return self.llvm_object.freeDecl(decl_index);
}
-pub fn flush(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
- return self.flushModule(comp, prog_node);
+pub fn flush(self: *NvPtx, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
+ return self.flushModule(arena, prog_node);
}
-pub fn flushModule(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
+pub fn flushModule(self: *NvPtx, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
if (build_options.skip_non_native)
@panic("Attempted to compile for architecture that was disabled by build configuration");
// The code that was here before mutated the Compilation's file emission mechanism.
// That's not supposed to happen in flushModule, so I deleted the code.
+ _ = arena;
_ = self;
- _ = comp;
_ = prog_node;
@panic("TODO: rewrite the NvPtx.flushModule function");
}
diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig
index e93c889dcd..a635b0bf5b 100644
--- a/src/link/Plan9.zig
+++ b/src/link/Plan9.zig
@@ -608,8 +608,9 @@ fn allocateGotIndex(self: *Plan9) usize {
}
}
-pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
- const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
+pub fn flush(self: *Plan9, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
+ const comp = self.base.comp;
+ const use_lld = build_options.have_llvm and comp.config.use_lld;
assert(!use_lld);
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
.Obj => return error.TODOImplementPlan9Objs,
.Lib => return error.TODOImplementWritingLibFiles,
}
- return self.flushModule(comp, prog_node);
+ return self.flushModule(arena, prog_node);
}
pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {
@@ -666,11 +667,14 @@ fn atomCount(self: *Plan9) usize {
return data_decl_count + fn_decl_count + unnamed_const_count + lazy_atom_count + extern_atom_count + anon_atom_count;
}
-pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
+pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
if (build_options.skip_non_native and builtin.object_format != .plan9) {
@panic("Attempted to compile for object format that was disabled by build configuration");
}
+ _ = arena; // Has the same lifetime as the call to Compilation.update.
+
+ const comp = self.base.comp;
const gpa = comp.gpa;
const target = comp.root_mod.resolved_target.result;
diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig
index fc9e0c9a60..7b66d914bf 100644
--- a/src/link/SpirV.zig
+++ b/src/link/SpirV.zig
@@ -173,15 +173,17 @@ pub fn freeDecl(self: *SpirV, decl_index: InternPool.DeclIndex) void {
_ = decl_index;
}
-pub fn flush(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
- return self.flushModule(comp, prog_node);
+pub fn flush(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
+ return self.flushModule(arena, prog_node);
}
-pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
+pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
if (build_options.skip_non_native) {
@panic("Attempted to compile for architecture that was disabled by build configuration");
}
+ _ = arena; // Has the same lifetime as the call to Compilation.update.
+
const tracy = trace(@src());
defer tracy.end();
@@ -191,6 +193,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
const spv = &self.object.spv;
+ const comp = self.base.comp;
const gpa = comp.gpa;
const target = comp.getTarget();
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index a0907d6c51..185d802588 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -3480,33 +3480,29 @@ fn resetState(wasm: *Wasm) void {
wasm.debug_pubtypes_index = null;
}
-pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
+pub fn flush(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
+ const comp = wasm.base.comp;
const use_lld = build_options.have_llvm and comp.config.use_lld;
const use_llvm = comp.config.use_llvm;
if (use_lld) {
- return wasm.linkWithLLD(comp, prog_node);
+ return wasm.linkWithLLD(arena, prog_node);
} else if (use_llvm) {
- return wasm.linkWithZld(comp, prog_node);
+ return wasm.linkWithZld(arena, prog_node);
} else {
- return wasm.flushModule(comp, prog_node);
+ return wasm.flushModule(arena, prog_node);
}
}
/// Uses the in-house linker to link one or multiple object -and archive files into a WebAssembly binary.
-fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
+fn linkWithZld(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
const tracy = trace(@src());
defer tracy.end();
- const gpa = comp.gpa;
+ const comp = wasm.base.comp;
const shared_memory = comp.config.shared_memory;
const import_memory = comp.config.import_memory;
- // Used for all temporary memory allocated during flushin
- var arena_instance = std.heap.ArenaAllocator.init(gpa);
- defer arena_instance.deinit();
- const arena = arena_instance.allocator();
-
const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.
const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});
const opt_zcu = comp.module;
@@ -3516,7 +3512,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
// will not be part of the linker line anyway.
const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {
assert(use_llvm); // `linkWithZld` should never be called when the Wasm backend is used
- try wasm.flushModule(comp, prog_node);
+ try wasm.flushModule(arena, prog_node);
if (fs.path.dirname(full_out_path)) |dirname| {
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
}
}
-pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
+pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
const tracy = trace(@src());
defer tracy.end();
- const gpa = comp.gpa;
- // Used for all temporary memory allocated during flushin
- var arena_instance = std.heap.ArenaAllocator.init(gpa);
- defer arena_instance.deinit();
- const arena = arena_instance.allocator();
+ const comp = wasm.base.comp;
if (wasm.llvm_object) |llvm_object| {
try wasm.base.emitLlvmObject(arena, llvm_object, prog_node);
@@ -4589,19 +4581,17 @@ fn emitImport(wasm: *Wasm, writer: anytype, import: types.Import) !void {
}
}
-fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
+fn linkWithLLD(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();
+ const comp = wasm.base.comp;
const shared_memory = comp.config.shared_memory;
const export_memory = comp.config.export_memory;
const import_memory = comp.config.import_memory;
const target = comp.root_mod.resolved_target.result;
const gpa = comp.gpa;
- var arena_allocator = std.heap.ArenaAllocator.init(gpa);
- defer arena_allocator.deinit();
- const arena = arena_allocator.allocator();
const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.
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) !
// If there is no Zig code to compile, then we should skip flushing the output file because it
// will not be part of the linker line anyway.
const module_obj_path: ?[]const u8 = if (comp.module != null) blk: {
- try wasm.flushModule(comp, prog_node);
+ try wasm.flushModule(arena, prog_node);
if (fs.path.dirname(full_out_path)) |dirname| {
break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });