diff --git a/src/Compilation.zig b/src/Compilation.zig index 98f4012a26..6c7f1d0d83 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2311,7 +2311,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void fn flush(comp: *Compilation, arena: Allocator, prog_node: *std.Progress.Node) !void { if (comp.bin_file) |lf| { // This is needed before reading the error flags. - lf.flush(comp, prog_node) catch |err| switch (err) { + lf.flush(arena, prog_node) catch |err| switch (err) { error.FlushFailure => {}, // error reported through link_error_flags error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr else => |e| return e, diff --git a/src/link.zig b/src/link.zig index 89f4125888..5c296b49ab 100644 --- a/src/link.zig +++ b/src/link.zig @@ -547,19 +547,22 @@ pub const File = struct { /// Commit pending changes and write headers. Takes into account final output mode /// and `use_lld`, not only `effectiveOutputMode`. - pub fn flush(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { + /// `arena` has the lifetime of the call to `Compilation.update`. + pub fn flush(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { if (build_options.only_c) { assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).flush(comp, prog_node); + return @fieldParentPtr(C, "base", base).flush(arena, prog_node); } + const comp = base.comp; if (comp.clang_preprocessor_mode == .yes) { + const gpa = comp.gpa; const emit = base.emit; // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case) // Until then, we do `lld -r -o output.o input.o` even though the output is the same // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file // to the final location. See also the corresponding TODO in Coff linking. - const full_out_path = try emit.directory.join(comp.gpa, &[_][]const u8{emit.sub_path}); - defer comp.gpa.free(full_out_path); + const full_out_path = try emit.directory.join(gpa, &[_][]const u8{emit.sub_path}); + defer gpa.free(full_out_path); assert(comp.c_object_table.count() == 1); const the_key = comp.c_object_table.keys()[0]; const cached_pp_file_path = the_key.status.success.object_path; @@ -571,25 +574,25 @@ pub const File = struct { const output_mode = comp.config.output_mode; const link_mode = comp.config.link_mode; if (use_lld and output_mode == .Lib and link_mode == .Static) { - return base.linkAsArchive(comp, prog_node); + return base.linkAsArchive(arena, prog_node); } switch (base.tag) { inline else => |tag| { - return @fieldParentPtr(tag.Type(), "base", base).flush(comp, prog_node); + return @fieldParentPtr(tag.Type(), "base", base).flush(arena, prog_node); }, } } /// Commit pending changes and write headers. Works based on `effectiveOutputMode` /// rather than final output mode. - pub fn flushModule(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { + pub fn flushModule(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { switch (base.tag) { .c => { - return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node); + return @fieldParentPtr(C, "base", base).flushModule(arena, prog_node); }, inline else => |tag| { if (build_options.only_c) unreachable; - return @fieldParentPtr(tag.Type(), "base", base).flushModule(comp, prog_node); + return @fieldParentPtr(tag.Type(), "base", base).flushModule(arena, prog_node); }, } } @@ -707,14 +710,12 @@ pub const File = struct { } } - pub fn linkAsArchive(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { + pub fn linkAsArchive(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { const tracy = trace(@src()); defer tracy.end(); + const comp = 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 = base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path}); @@ -724,7 +725,7 @@ pub const File = struct { // 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 zcu_obj_path: ?[]const u8 = if (opt_zcu != null) blk: { - try base.flushModule(comp, prog_node); + try base.flushModule(arena, prog_node); const dirname = fs.path.dirname(full_out_path_z) orelse "."; break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? }); 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.? });