| author | |
| committer | |
| log | d5c1e7f7b1381036f7d98c1944607cb0e1c0d4da |
| tree | f78506c79713b855ed8f23426ce78e0e292e13ee |
| parent | eae6d45cded76dd027569c86a7cdd5bc9039664b |
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 |
| 2311 | fn flush(comp: *Compilation, arena: Allocator, prog_node: *std.Progress.Node) !void { | 2311 | fn 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_flags | 2315 | error.FlushFailure => {}, // error reported through link_error_flags |
| 2316 | error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr | 2316 | 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 { |
| 547 | 547 | ||
| 548 | /// Commit pending changes and write headers. Takes into account final output mode | 548 | /// 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 same | 561 | // 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 file | 562 | // 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 | } |
| 582 | 585 | ||
| 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 | } |
| 709 | 712 | ||
| 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(); |
| 713 | 716 | ||
| 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(); | ||
| 718 | 719 | ||
| 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 file | 725 | // 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); |
| 728 | 729 | ||
| 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 | } |
| 378 | 378 | ||
| 379 | pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 379 | pub 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 | } |
| 382 | 382 | ||
| 383 | fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) { | 383 | 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,7 +393,9 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) { |
| 393 | return defines; | 393 | return defines; |
| 394 | } | 394 | } |
| 395 | 395 | ||
| 396 | pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !void { | 396 | pub 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(); |
| 399 | 401 | ||
| ... | @@ -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(); |
| 403 | 405 | ||
| 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.?; |
| 406 | 409 | ||
| 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 | } |
| 1708 | 1708 | ||
| 1709 | pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 1709 | pub 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 | } |
| 1719 | 1720 | ||
| 1720 | pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 1721 | pub 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(); |
| 1723 | 1724 | ||
| 1725 | const comp = self.base.comp; | ||
| 1724 | const gpa = comp.gpa; | 1726 | const gpa = comp.gpa; |
| 1725 | 1727 | ||
| 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; |
| 17 | const Coff = @import("../Coff.zig"); | 17 | const Coff = @import("../Coff.zig"); |
| 18 | const Compilation = @import("../../Compilation.zig"); | 18 | const Compilation = @import("../../Compilation.zig"); |
| 19 | 19 | ||
| 20 | pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 20 | pub 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(); |
| 23 | 23 | ||
| 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(); | ||
| 28 | 26 | ||
| 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 it | 30 | // 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); |
| 36 | 34 | ||
| 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 | } |
| 1028 | 1028 | ||
| 1029 | pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 1029 | pub 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 | } |
| 1036 | 1036 | ||
| 1037 | pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 1037 | pub 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(); |
| 1040 | 1040 | ||
| 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(); | ||
| 1045 | 1043 | ||
| 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 | } |
| 2351 | 2349 | ||
| 2352 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 2350 | fn 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(); |
| 2355 | 2353 | ||
| 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(); | ||
| 2360 | 2356 | ||
| 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}); |
| 2363 | 2359 | ||
| 2364 | // If there is no Zig code to compile, then we should skip flushing the output file because it | 2360 | // 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); |
| 2368 | 2364 | ||
| 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(); |
| 2380 | 2376 | ||
| 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 and | 2383 | 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 namespace | 2456 | // 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 | } |
| 2772 | 2768 | ||
| 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 |
| 2841 | 2837 | ||
| 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(); |
| 2846 | 2842 | ||
| 2847 | // Worst-case, we need an --as-needed argument for every lib, as well | 2843 | // 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 dep | 2886 | // 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 | } |
| 2941 | 2937 | ||
| 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 | } |
| 317 | 317 | ||
| 318 | pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 318 | pub 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; | ||
| 321 | 322 | ||
| 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 | } |
| 333 | 334 | ||
| 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 | } |
| 339 | 340 | ||
| 340 | pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 341 | pub 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(); |
| 343 | 344 | ||
| 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(); | ||
| 348 | 347 | ||
| 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 @@ |
| 1 | pub fn linkWithZld( | 1 | pub 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(); |
| 8 | 8 | ||
| 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; |
| 12 | 13 | ||
| 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; |
| 20 | 17 | ||
| 21 | // If there is no Zig code to compile, then we should skip flushing the output file because it | 18 | // 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); |
| 25 | 22 | ||
| 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(); |
| 37 | 34 | ||
| 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( |
| 50 | 47 | ||
| 51 | var digest: [Cache.hex_digest_len]u8 = undefined; | 48 | var digest: [Cache.hex_digest_len]u8 = undefined; |
| 52 | 49 | ||
| 53 | const objects = macho_file.base.comp.objects; | 50 | const objects = comp.objects; |
| 54 | 51 | ||
| 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(); |
| 408 | 405 | ||
| 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 | } |
| 108 | 108 | ||
| 109 | pub fn flush(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 109 | pub 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 | } |
| 112 | 112 | ||
| 113 | pub fn flushModule(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 113 | pub 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"); |
| 116 | 116 | ||
| 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 | } |
| 610 | 610 | ||
| 611 | pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 611 | pub 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); |
| 614 | 615 | ||
| 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 | } |
| 623 | 624 | ||
| 624 | pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void { | 625 | pub 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 | } |
| 668 | 669 | ||
| 669 | pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 670 | pub 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 | } |
| 673 | 674 | ||
| 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; |
| 676 | 680 |
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 | } |
| 175 | 175 | ||
| 176 | pub fn flush(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 176 | pub 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 | } |
| 179 | 179 | ||
| 180 | pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 180 | pub 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 | } |
| 184 | 184 | ||
| 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(); |
| 187 | 189 | ||
| ... | @@ -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 |
| 191 | 193 | ||
| 192 | const spv = &self.object.spv; | 194 | const spv = &self.object.spv; |
| 193 | 195 | ||
| 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(); |
| 196 | 199 |
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 | } |
| 3482 | 3482 | ||
| 3483 | pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 3483 | pub 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; |
| 3486 | 3487 | ||
| 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 | } |
| 3495 | 3496 | ||
| 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. |
| 3497 | fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 3498 | fn 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(); |
| 3500 | 3501 | ||
| 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; |
| 3504 | 3505 | ||
| 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 used | 3514 | 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); |
| 3520 | 3516 | ||
| 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 | } |
| 3710 | 3706 | ||
| 3711 | pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 3707 | pub 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(); |
| 3714 | 3710 | ||
| 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(); | ||
| 3720 | 3712 | ||
| 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 | } |
| 4591 | 4583 | ||
| 4592 | fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 4584 | fn 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(); |
| 4595 | 4587 | ||
| 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; |
| 4600 | 4593 | ||
| 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(); | ||
| 4605 | 4595 | ||
| 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 it | 4599 | // 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); |
| 4613 | 4603 | ||
| 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.? }); |