authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-17 04:06:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-17 04:09:35-07:00
loga7c05c06bef1570546cae4c45a76027819c7fa09
tree80ae95c7d5edf95f4ed8ed013eb0bf9e27e337fb
parent2aeaa1cfc4c563a24525fb27fd2783bfd5da808a

stage2: expose progress bar API to linker backends

This gives us insight as to what is happening when we are waiting for things such as LLVM emit object and LLD linking.

11 files changed, 134 insertions(+), 83 deletions(-)

src/Compilation.zig+16-14
...@@ -2084,7 +2084,13 @@ pub fn update(comp: *Compilation) !void {...@@ -2084,7 +2084,13 @@ pub fn update(comp: *Compilation) !void {
2084 }2084 }
2085 }2085 }
20862086
2087 try comp.performAllTheWork();2087 // If the terminal is dumb, we dont want to show the user all the output.
2088 var progress: std.Progress = .{ .dont_print_on_dumb = true };
2089 const main_progress_node = progress.start("", 0);
2090 defer main_progress_node.end();
2091 if (comp.color == .off) progress.terminal = null;
2092
2093 try comp.performAllTheWork(main_progress_node);
20882094
2089 if (!use_stage1) {2095 if (!use_stage1) {
2090 if (comp.bin_file.options.module) |module| {2096 if (comp.bin_file.options.module) |module| {
...@@ -2158,9 +2164,9 @@ pub fn update(comp: *Compilation) !void {...@@ -2158,9 +2164,9 @@ pub fn update(comp: *Compilation) !void {
2158 .path = dir_path,2164 .path = dir_path,
2159 };2165 };
21602166
2161 try comp.flush();2167 try comp.flush(main_progress_node);
2162 } else {2168 } else {
2163 try comp.flush();2169 try comp.flush(main_progress_node);
2164 }2170 }
21652171
2166 // Failure here only means an unnecessary cache miss.2172 // Failure here only means an unnecessary cache miss.
...@@ -2171,7 +2177,7 @@ pub fn update(comp: *Compilation) !void {...@@ -2171,7 +2177,7 @@ pub fn update(comp: *Compilation) !void {
2171 assert(comp.bin_file.lock == null);2177 assert(comp.bin_file.lock == null);
2172 comp.bin_file.lock = man.toOwnedLock();2178 comp.bin_file.lock = man.toOwnedLock();
2173 } else {2179 } else {
2174 try comp.flush();2180 try comp.flush(main_progress_node);
2175 }2181 }
21762182
2177 // Unload all source files to save memory.2183 // Unload all source files to save memory.
...@@ -2188,8 +2194,8 @@ pub fn update(comp: *Compilation) !void {...@@ -2188,8 +2194,8 @@ pub fn update(comp: *Compilation) !void {
2188 }2194 }
2189}2195}
21902196
2191fn flush(comp: *Compilation) !void {2197fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void {
2192 try comp.bin_file.flush(comp); // This is needed before reading the error flags.2198 try comp.bin_file.flush(comp, prog_node); // This is needed before reading the error flags.
2193 comp.link_error_flags = comp.bin_file.errorFlags();2199 comp.link_error_flags = comp.bin_file.errorFlags();
21942200
2195 const use_stage1 = build_options.omit_stage2 or2201 const use_stage1 = build_options.omit_stage2 or
...@@ -2590,14 +2596,10 @@ pub fn getCompileLogOutput(self: *Compilation) []const u8 {...@@ -2590,14 +2596,10 @@ pub fn getCompileLogOutput(self: *Compilation) []const u8 {
2590 return module.compile_log_text.items;2596 return module.compile_log_text.items;
2591}2597}
25922598
2593pub fn performAllTheWork(comp: *Compilation) error{ TimerUnsupported, OutOfMemory }!void {2599pub fn performAllTheWork(
2594 // If the terminal is dumb, we dont want to show the user all the2600 comp: *Compilation,
2595 // output.2601 main_progress_node: *std.Progress.Node,
2596 var progress: std.Progress = .{ .dont_print_on_dumb = true };2602) error{ TimerUnsupported, OutOfMemory }!void {
2597 var main_progress_node = progress.start("", 0);
2598 defer main_progress_node.end();
2599 if (comp.color == .off) progress.terminal = null;
2600
2601 // Here we queue up all the AstGen tasks first, followed by C object compilation.2603 // Here we queue up all the AstGen tasks first, followed by C object compilation.
2602 // We wait until the AstGen tasks are all completed before proceeding to the2604 // We wait until the AstGen tasks are all completed before proceeding to the
2603 // (at least for now) single-threaded main work queue. However, C object compilation2605 // (at least for now) single-threaded main work queue. However, C object compilation
src/codegen/llvm.zig+6-1
...@@ -469,7 +469,12 @@ pub const Object = struct {...@@ -469,7 +469,12 @@ pub const Object = struct {
469 _ = builder.buildRet(is_lt);469 _ = builder.buildRet(is_lt);
470 }470 }
471471
472 pub fn flushModule(self: *Object, comp: *Compilation) !void {472 pub fn flushModule(self: *Object, comp: *Compilation, prog_node: *std.Progress.Node) !void {
473 var sub_prog_node = prog_node.start("LLVM Emit Object", 0);
474 sub_prog_node.activate();
475 sub_prog_node.context.refresh();
476 defer sub_prog_node.end();
477
473 try self.genErrorNameTable(comp);478 try self.genErrorNameTable(comp);
474 try self.genCmpLtErrorsLenFunction(comp);479 try self.genCmpLtErrorsLenFunction(comp);
475480
src/link.zig+22-22
...@@ -573,7 +573,7 @@ pub const File = struct {...@@ -573,7 +573,7 @@ pub const File = struct {
573573
574 /// Commit pending changes and write headers. Takes into account final output mode574 /// Commit pending changes and write headers. Takes into account final output mode
575 /// and `use_lld`, not only `effectiveOutputMode`.575 /// and `use_lld`, not only `effectiveOutputMode`.
576 pub fn flush(base: *File, comp: *Compilation) !void {576 pub fn flush(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) !void {
577 if (comp.clang_preprocessor_mode == .yes) {577 if (comp.clang_preprocessor_mode == .yes) {
578 const emit = base.options.emit orelse return; // -fno-emit-bin578 const emit = base.options.emit orelse return; // -fno-emit-bin
579 // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)579 // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)
...@@ -591,32 +591,32 @@ pub const File = struct {...@@ -591,32 +591,32 @@ pub const File = struct {
591591
592 const use_lld = build_options.have_llvm and base.options.use_lld;592 const use_lld = build_options.have_llvm and base.options.use_lld;
593 if (use_lld and base.options.output_mode == .Lib and base.options.link_mode == .Static) {593 if (use_lld and base.options.output_mode == .Lib and base.options.link_mode == .Static) {
594 return base.linkAsArchive(comp);594 return base.linkAsArchive(comp, prog_node);
595 }595 }
596 switch (base.tag) {596 switch (base.tag) {
597 .coff => return @fieldParentPtr(Coff, "base", base).flush(comp),597 .coff => return @fieldParentPtr(Coff, "base", base).flush(comp, prog_node),
598 .elf => return @fieldParentPtr(Elf, "base", base).flush(comp),598 .elf => return @fieldParentPtr(Elf, "base", base).flush(comp, prog_node),
599 .macho => return @fieldParentPtr(MachO, "base", base).flush(comp),599 .macho => return @fieldParentPtr(MachO, "base", base).flush(comp, prog_node),
600 .c => return @fieldParentPtr(C, "base", base).flush(comp),600 .c => return @fieldParentPtr(C, "base", base).flush(comp, prog_node),
601 .wasm => return @fieldParentPtr(Wasm, "base", base).flush(comp),601 .wasm => return @fieldParentPtr(Wasm, "base", base).flush(comp, prog_node),
602 .spirv => return @fieldParentPtr(SpirV, "base", base).flush(comp),602 .spirv => return @fieldParentPtr(SpirV, "base", base).flush(comp, prog_node),
603 .plan9 => return @fieldParentPtr(Plan9, "base", base).flush(comp),603 .plan9 => return @fieldParentPtr(Plan9, "base", base).flush(comp, prog_node),
604 .nvptx => return @fieldParentPtr(NvPtx, "base", base).flush(comp),604 .nvptx => return @fieldParentPtr(NvPtx, "base", base).flush(comp, prog_node),
605 }605 }
606 }606 }
607607
608 /// Commit pending changes and write headers. Works based on `effectiveOutputMode`608 /// Commit pending changes and write headers. Works based on `effectiveOutputMode`
609 /// rather than final output mode.609 /// rather than final output mode.
610 pub fn flushModule(base: *File, comp: *Compilation) !void {610 pub fn flushModule(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) !void {
611 switch (base.tag) {611 switch (base.tag) {
612 .coff => return @fieldParentPtr(Coff, "base", base).flushModule(comp),612 .coff => return @fieldParentPtr(Coff, "base", base).flushModule(comp, prog_node),
613 .elf => return @fieldParentPtr(Elf, "base", base).flushModule(comp),613 .elf => return @fieldParentPtr(Elf, "base", base).flushModule(comp, prog_node),
614 .macho => return @fieldParentPtr(MachO, "base", base).flushModule(comp),614 .macho => return @fieldParentPtr(MachO, "base", base).flushModule(comp, prog_node),
615 .c => return @fieldParentPtr(C, "base", base).flushModule(comp),615 .c => return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node),
616 .wasm => return @fieldParentPtr(Wasm, "base", base).flushModule(comp),616 .wasm => return @fieldParentPtr(Wasm, "base", base).flushModule(comp, prog_node),
617 .spirv => return @fieldParentPtr(SpirV, "base", base).flushModule(comp),617 .spirv => return @fieldParentPtr(SpirV, "base", base).flushModule(comp, prog_node),
618 .plan9 => return @fieldParentPtr(Plan9, "base", base).flushModule(comp),618 .plan9 => return @fieldParentPtr(Plan9, "base", base).flushModule(comp, prog_node),
619 .nvptx => return @fieldParentPtr(NvPtx, "base", base).flushModule(comp),619 .nvptx => return @fieldParentPtr(NvPtx, "base", base).flushModule(comp, prog_node),
620 }620 }
621 }621 }
622622
...@@ -754,7 +754,7 @@ pub const File = struct {...@@ -754,7 +754,7 @@ pub const File = struct {
754 }754 }
755 }755 }
756756
757 pub fn linkAsArchive(base: *File, comp: *Compilation) !void {757 pub fn linkAsArchive(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) !void {
758 const tracy = trace(@src());758 const tracy = trace(@src());
759 defer tracy.end();759 defer tracy.end();
760760
...@@ -787,9 +787,9 @@ pub const File = struct {...@@ -787,9 +787,9 @@ pub const File = struct {
787 }787 }
788 }788 }
789 if (base.options.object_format == .macho) {789 if (base.options.object_format == .macho) {
790 try base.cast(MachO).?.flushObject(comp);790 try base.cast(MachO).?.flushObject(comp, prog_node);
791 } else {791 } else {
792 try base.flushModule(comp);792 try base.flushModule(comp, prog_node);
793 }793 }
794 break :blk try fs.path.join(arena, &.{794 break :blk try fs.path.join(arena, &.{
795 fs.path.dirname(full_out_path_z).?, base.intermediary_basename.?,795 fs.path.dirname(full_out_path_z).?, base.intermediary_basename.?,
src/link/C.zig+7-3
...@@ -235,14 +235,18 @@ pub fn updateDeclLineNumber(self: *C, module: *Module, decl: *Module.Decl) !void...@@ -235,14 +235,18 @@ pub fn updateDeclLineNumber(self: *C, module: *Module, decl: *Module.Decl) !void
235 _ = decl;235 _ = decl;
236}236}
237237
238pub fn flush(self: *C, comp: *Compilation) !void {238pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void {
239 return self.flushModule(comp);239 return self.flushModule(comp, prog_node);
240}240}
241241
242pub fn flushModule(self: *C, comp: *Compilation) !void {242pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void {
243 const tracy = trace(@src());243 const tracy = trace(@src());
244 defer tracy.end();244 defer tracy.end();
245245
246 var sub_prog_node = prog_node.start("Flush Module", 0);
247 sub_prog_node.activate();
248 defer sub_prog_node.end();
249
246 const gpa = comp.gpa;250 const gpa = comp.gpa;
247 const module = self.base.options.module.?;251 const module = self.base.options.module.?;
248252
src/link/Coff.zig+17-8
...@@ -829,36 +829,40 @@ pub fn updateDeclExports(...@@ -829,36 +829,40 @@ pub fn updateDeclExports(
829 }829 }
830}830}
831831
832pub fn flush(self: *Coff, comp: *Compilation) !void {832pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {
833 if (self.base.options.emit == null) {833 if (self.base.options.emit == null) {
834 if (build_options.have_llvm) {834 if (build_options.have_llvm) {
835 if (self.llvm_object) |llvm_object| {835 if (self.llvm_object) |llvm_object| {
836 return try llvm_object.flushModule(comp);836 return try llvm_object.flushModule(comp, prog_node);
837 }837 }
838 }838 }
839 return;839 return;
840 }840 }
841 if (build_options.have_llvm and self.base.options.use_lld) {841 if (build_options.have_llvm and self.base.options.use_lld) {
842 return self.linkWithLLD(comp);842 return self.linkWithLLD(comp, prog_node);
843 } else {843 } else {
844 switch (self.base.options.effectiveOutputMode()) {844 switch (self.base.options.effectiveOutputMode()) {
845 .Exe, .Obj => {},845 .Exe, .Obj => {},
846 .Lib => return error.TODOImplementWritingLibFiles,846 .Lib => return error.TODOImplementWritingLibFiles,
847 }847 }
848 return self.flushModule(comp);848 return self.flushModule(comp, prog_node);
849 }849 }
850}850}
851851
852pub fn flushModule(self: *Coff, comp: *Compilation) !void {852pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {
853 const tracy = trace(@src());853 const tracy = trace(@src());
854 defer tracy.end();854 defer tracy.end();
855855
856 if (build_options.have_llvm) {856 if (build_options.have_llvm) {
857 if (self.llvm_object) |llvm_object| {857 if (self.llvm_object) |llvm_object| {
858 return try llvm_object.flushModule(comp);858 return try llvm_object.flushModule(comp, prog_node);
859 }859 }
860 }860 }
861861
862 var sub_prog_node = prog_node.start("COFF Flush", 0);
863 sub_prog_node.activate();
864 defer sub_prog_node.end();
865
862 if (self.text_section_size_dirty) {866 if (self.text_section_size_dirty) {
863 // Write the new raw size in the .text header867 // Write the new raw size in the .text header
864 var buf: [4]u8 = undefined;868 var buf: [4]u8 = undefined;
...@@ -892,7 +896,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {...@@ -892,7 +896,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
892 }896 }
893}897}
894898
895fn linkWithLLD(self: *Coff, comp: *Compilation) !void {899fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {
896 const tracy = trace(@src());900 const tracy = trace(@src());
897 defer tracy.end();901 defer tracy.end();
898902
...@@ -924,7 +928,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -924,7 +928,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
924 }928 }
925 }929 }
926930
927 try self.flushModule(comp);931 try self.flushModule(comp, prog_node);
928932
929 if (fs.path.dirname(full_out_path)) |dirname| {933 if (fs.path.dirname(full_out_path)) |dirname| {
930 break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? });934 break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? });
...@@ -933,6 +937,11 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -933,6 +937,11 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
933 }937 }
934 } else null;938 } else null;
935939
940 var sub_prog_node = prog_node.start("LLD Link", 0);
941 sub_prog_node.activate();
942 sub_prog_node.context.refresh();
943 defer sub_prog_node.end();
944
936 const is_lib = self.base.options.output_mode == .Lib;945 const is_lib = self.base.options.output_mode == .Lib;
937 const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;946 const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;
938 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;947 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
src/link/Elf.zig+17-8
...@@ -929,35 +929,39 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -929,35 +929,39 @@ pub fn populateMissingMetadata(self: *Elf) !void {
929 }929 }
930}930}
931931
932pub fn flush(self: *Elf, comp: *Compilation) !void {932pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
933 if (self.base.options.emit == null) {933 if (self.base.options.emit == null) {
934 if (build_options.have_llvm) {934 if (build_options.have_llvm) {
935 if (self.llvm_object) |llvm_object| {935 if (self.llvm_object) |llvm_object| {
936 return try llvm_object.flushModule(comp);936 return try llvm_object.flushModule(comp, prog_node);
937 }937 }
938 }938 }
939 return;939 return;
940 }940 }
941 const use_lld = build_options.have_llvm and self.base.options.use_lld;941 const use_lld = build_options.have_llvm and self.base.options.use_lld;
942 if (use_lld) {942 if (use_lld) {
943 return self.linkWithLLD(comp);943 return self.linkWithLLD(comp, prog_node);
944 }944 }
945 switch (self.base.options.output_mode) {945 switch (self.base.options.output_mode) {
946 .Exe, .Obj => return self.flushModule(comp),946 .Exe, .Obj => return self.flushModule(comp, prog_node),
947 .Lib => return error.TODOImplementWritingLibFiles,947 .Lib => return error.TODOImplementWritingLibFiles,
948 }948 }
949}949}
950950
951pub fn flushModule(self: *Elf, comp: *Compilation) !void {951pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
952 const tracy = trace(@src());952 const tracy = trace(@src());
953 defer tracy.end();953 defer tracy.end();
954954
955 if (build_options.have_llvm) {955 if (build_options.have_llvm) {
956 if (self.llvm_object) |llvm_object| {956 if (self.llvm_object) |llvm_object| {
957 return try llvm_object.flushModule(comp);957 return try llvm_object.flushModule(comp, prog_node);
958 }958 }
959 }959 }
960960
961 var sub_prog_node = prog_node.start("ELF Flush", 0);
962 sub_prog_node.activate();
963 defer sub_prog_node.end();
964
961 // TODO This linker code currently assumes there is only 1 compilation unit and it965 // TODO This linker code currently assumes there is only 1 compilation unit and it
962 // corresponds to the Zig source code.966 // corresponds to the Zig source code.
963 const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;967 const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
...@@ -1204,7 +1208,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {...@@ -1204,7 +1208,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
1204 assert(!self.debug_strtab_dirty);1208 assert(!self.debug_strtab_dirty);
1205}1209}
12061210
1207fn linkWithLLD(self: *Elf, comp: *Compilation) !void {1211fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
1208 const tracy = trace(@src());1212 const tracy = trace(@src());
1209 defer tracy.end();1213 defer tracy.end();
12101214
...@@ -1236,7 +1240,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1236,7 +1240,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1236 }1240 }
1237 }1241 }
12381242
1239 try self.flushModule(comp);1243 try self.flushModule(comp, prog_node);
12401244
1241 if (fs.path.dirname(full_out_path)) |dirname| {1245 if (fs.path.dirname(full_out_path)) |dirname| {
1242 break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? });1246 break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? });
...@@ -1245,6 +1249,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1245,6 +1249,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1245 }1249 }
1246 } else null;1250 } else null;
12471251
1252 var sub_prog_node = prog_node.start("LLD Link", 0);
1253 sub_prog_node.activate();
1254 sub_prog_node.context.refresh();
1255 defer sub_prog_node.end();
1256
1248 const is_obj = self.base.options.output_mode == .Obj;1257 const is_obj = self.base.options.output_mode == .Obj;
1249 const is_lib = self.base.options.output_mode == .Lib;1258 const is_lib = self.base.options.output_mode == .Lib;
1250 const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;1259 const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;
src/link/MachO.zig+14-9
...@@ -419,33 +419,34 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {...@@ -419,33 +419,34 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {
419 return self;419 return self;
420}420}
421421
422pub fn flush(self: *MachO, comp: *Compilation) !void {422pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) !void {
423 if (self.base.options.emit == null) {423 if (self.base.options.emit == null) {
424 if (build_options.have_llvm) {424 if (build_options.have_llvm) {
425 if (self.llvm_object) |llvm_object| {425 if (self.llvm_object) |llvm_object| {
426 try llvm_object.flushModule(comp);426 try llvm_object.flushModule(comp, prog_node);
427 }427 }
428 }428 }
429 return;429 return;
430 }430 }
431
431 if (self.base.options.output_mode == .Lib and self.base.options.link_mode == .Static) {432 if (self.base.options.output_mode == .Lib and self.base.options.link_mode == .Static) {
432 if (build_options.have_llvm) {433 if (build_options.have_llvm) {
433 return self.base.linkAsArchive(comp);434 return self.base.linkAsArchive(comp, prog_node);
434 } else {435 } else {
435 log.err("TODO: non-LLVM archiver for MachO object files", .{});436 log.err("TODO: non-LLVM archiver for MachO object files", .{});
436 return error.TODOImplementWritingStaticLibFiles;437 return error.TODOImplementWritingStaticLibFiles;
437 }438 }
438 }439 }
439 try self.flushModule(comp);440 try self.flushModule(comp, prog_node);
440}441}
441442
442pub fn flushModule(self: *MachO, comp: *Compilation) !void {443pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) !void {
443 const tracy = trace(@src());444 const tracy = trace(@src());
444 defer tracy.end();445 defer tracy.end();
445446
446 const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1;447 const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1;
447 if (!use_stage1 and self.base.options.output_mode == .Obj)448 if (!use_stage1 and self.base.options.output_mode == .Obj)
448 return self.flushObject(comp);449 return self.flushObject(comp, prog_node);
449450
450 var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator);451 var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator);
451 defer arena_allocator.deinit();452 defer arena_allocator.deinit();
...@@ -482,7 +483,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -482,7 +483,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
482483
483 const obj_basename = self.base.intermediary_basename orelse break :blk null;484 const obj_basename = self.base.intermediary_basename orelse break :blk null;
484485
485 try self.flushObject(comp);486 try self.flushObject(comp, prog_node);
486487
487 if (fs.path.dirname(full_out_path)) |dirname| {488 if (fs.path.dirname(full_out_path)) |dirname| {
488 break :blk try fs.path.join(arena, &.{ dirname, obj_basename });489 break :blk try fs.path.join(arena, &.{ dirname, obj_basename });
...@@ -491,6 +492,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -491,6 +492,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
491 }492 }
492 } else null;493 } else null;
493494
495 var sub_prog_node = prog_node.start("MachO Flush", 0);
496 sub_prog_node.activate();
497 defer sub_prog_node.end();
498
494 const is_lib = self.base.options.output_mode == .Lib;499 const is_lib = self.base.options.output_mode == .Lib;
495 const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;500 const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;
496 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;501 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
...@@ -1111,13 +1116,13 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -1111,13 +1116,13 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
1111 self.cold_start = false;1116 self.cold_start = false;
1112}1117}
11131118
1114pub fn flushObject(self: *MachO, comp: *Compilation) !void {1119pub fn flushObject(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) !void {
1115 const tracy = trace(@src());1120 const tracy = trace(@src());
1116 defer tracy.end();1121 defer tracy.end();
11171122
1118 if (build_options.have_llvm)1123 if (build_options.have_llvm)
1119 if (self.llvm_object) |llvm_object|1124 if (self.llvm_object) |llvm_object|
1120 return llvm_object.flushModule(comp);1125 return llvm_object.flushModule(comp, prog_node);
11211126
1122 return error.TODOImplementWritingObjFiles;1127 return error.TODOImplementWritingObjFiles;
1123}1128}
src/link/NvPtx.zig+4-4
...@@ -97,11 +97,11 @@ pub fn freeDecl(self: *NvPtx, decl: *Module.Decl) void {...@@ -97,11 +97,11 @@ pub fn freeDecl(self: *NvPtx, decl: *Module.Decl) void {
97 return self.llvm_object.freeDecl(decl);97 return self.llvm_object.freeDecl(decl);
98}98}
9999
100pub fn flush(self: *NvPtx, comp: *Compilation) !void {100pub fn flush(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) !void {
101 return self.flushModule(comp);101 return self.flushModule(comp, prog_node);
102}102}
103103
104pub fn flushModule(self: *NvPtx, comp: *Compilation) !void {104pub fn flushModule(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) !void {
105 if (!build_options.have_llvm) return;105 if (!build_options.have_llvm) return;
106 if (build_options.skip_non_native) {106 if (build_options.skip_non_native) {
107 @panic("Attempted to compile for architecture that was disabled by build configuration");107 @panic("Attempted to compile for architecture that was disabled by build configuration");
...@@ -117,5 +117,5 @@ pub fn flushModule(self: *NvPtx, comp: *Compilation) !void {...@@ -117,5 +117,5 @@ pub fn flushModule(self: *NvPtx, comp: *Compilation) !void {
117 };117 };
118 hack_comp.bin_file.options.emit = null;118 hack_comp.bin_file.options.emit = null;
119 }119 }
120 return try self.llvm_object.flushModule(hack_comp);120 return try self.llvm_object.flushModule(hack_comp, prog_node);
121}121}
src/link/Plan9.zig+7-3
...@@ -351,7 +351,7 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void {...@@ -351,7 +351,7 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void {
351 }351 }
352}352}
353353
354pub fn flush(self: *Plan9, comp: *Compilation) !void {354pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) !void {
355 assert(!self.base.options.use_lld);355 assert(!self.base.options.use_lld);
356356
357 switch (self.base.options.effectiveOutputMode()) {357 switch (self.base.options.effectiveOutputMode()) {
...@@ -360,7 +360,7 @@ pub fn flush(self: *Plan9, comp: *Compilation) !void {...@@ -360,7 +360,7 @@ pub fn flush(self: *Plan9, comp: *Compilation) !void {
360 .Obj => return error.TODOImplementPlan9Objs,360 .Obj => return error.TODOImplementPlan9Objs,
361 .Lib => return error.TODOImplementWritingLibFiles,361 .Lib => return error.TODOImplementWritingLibFiles,
362 }362 }
363 return self.flushModule(comp);363 return self.flushModule(comp, prog_node);
364}364}
365365
366pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {366pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {
...@@ -387,7 +387,7 @@ fn declCount(self: *Plan9) usize {...@@ -387,7 +387,7 @@ fn declCount(self: *Plan9) usize {
387 return self.data_decl_table.count() + fn_decl_count;387 return self.data_decl_table.count() + fn_decl_count;
388}388}
389389
390pub fn flushModule(self: *Plan9, comp: *Compilation) !void {390pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) !void {
391 if (build_options.skip_non_native and builtin.object_format != .plan9) {391 if (build_options.skip_non_native and builtin.object_format != .plan9) {
392 @panic("Attempted to compile for object format that was disabled by build configuration");392 @panic("Attempted to compile for object format that was disabled by build configuration");
393 }393 }
...@@ -396,6 +396,10 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {...@@ -396,6 +396,10 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {
396 const tracy = trace(@src());396 const tracy = trace(@src());
397 defer tracy.end();397 defer tracy.end();
398398
399 var sub_prog_node = prog_node.start("Flush Module", 0);
400 sub_prog_node.activate();
401 defer sub_prog_node.end();
402
399 log.debug("flushModule", .{});403 log.debug("flushModule", .{});
400404
401 defer assert(self.hdr.entry != 0x0);405 defer assert(self.hdr.entry != 0x0);
src/link/SpirV.zig+7-3
...@@ -174,15 +174,15 @@ pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void {...@@ -174,15 +174,15 @@ pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void {
174 self.decl_table.swapRemoveAt(index);174 self.decl_table.swapRemoveAt(index);
175}175}
176176
177pub fn flush(self: *SpirV, comp: *Compilation) !void {177pub fn flush(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) !void {
178 if (build_options.have_llvm and self.base.options.use_lld) {178 if (build_options.have_llvm and self.base.options.use_lld) {
179 return error.LLD_LinkingIsTODO_ForSpirV; // TODO: LLD Doesn't support SpirV at all.179 return error.LLD_LinkingIsTODO_ForSpirV; // TODO: LLD Doesn't support SpirV at all.
180 } else {180 } else {
181 return self.flushModule(comp);181 return self.flushModule(comp, prog_node);
182 }182 }
183}183}
184184
185pub fn flushModule(self: *SpirV, comp: *Compilation) !void {185pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) !void {
186 if (build_options.skip_non_native) {186 if (build_options.skip_non_native) {
187 @panic("Attempted to compile for architecture that was disabled by build configuration");187 @panic("Attempted to compile for architecture that was disabled by build configuration");
188 }188 }
...@@ -190,6 +190,10 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {...@@ -190,6 +190,10 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {
190 const tracy = trace(@src());190 const tracy = trace(@src());
191 defer tracy.end();191 defer tracy.end();
192192
193 var sub_prog_node = prog_node.start("Flush Module", 0);
194 sub_prog_node.activate();
195 defer sub_prog_node.end();
196
193 const module = self.base.options.module.?;197 const module = self.base.options.module.?;
194 const target = comp.getTarget();198 const target = comp.getTarget();
195199
src/link/Wasm.zig+17-8
...@@ -1477,32 +1477,36 @@ fn resetState(self: *Wasm) void {...@@ -1477,32 +1477,36 @@ fn resetState(self: *Wasm) void {
1477 self.code_section_index = null;1477 self.code_section_index = null;
1478}1478}
14791479
1480pub fn flush(self: *Wasm, comp: *Compilation) !void {1480pub fn flush(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
1481 if (self.base.options.emit == null) {1481 if (self.base.options.emit == null) {
1482 if (build_options.have_llvm) {1482 if (build_options.have_llvm) {
1483 if (self.llvm_object) |llvm_object| {1483 if (self.llvm_object) |llvm_object| {
1484 return try llvm_object.flushModule(comp);1484 return try llvm_object.flushModule(comp, prog_node);
1485 }1485 }
1486 }1486 }
1487 return;1487 return;
1488 }1488 }
1489 if (build_options.have_llvm and self.base.options.use_lld) {1489 if (build_options.have_llvm and self.base.options.use_lld) {
1490 return self.linkWithLLD(comp);1490 return self.linkWithLLD(comp, prog_node);
1491 } else {1491 } else {
1492 return self.flushModule(comp);1492 return self.flushModule(comp, prog_node);
1493 }1493 }
1494}1494}
14951495
1496pub fn flushModule(self: *Wasm, comp: *Compilation) !void {1496pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
1497 const tracy = trace(@src());1497 const tracy = trace(@src());
1498 defer tracy.end();1498 defer tracy.end();
14991499
1500 if (build_options.have_llvm) {1500 if (build_options.have_llvm) {
1501 if (self.llvm_object) |llvm_object| {1501 if (self.llvm_object) |llvm_object| {
1502 return try llvm_object.flushModule(comp);1502 return try llvm_object.flushModule(comp, prog_node);
1503 }1503 }
1504 }1504 }
15051505
1506 var sub_prog_node = prog_node.start("WASM Flush", 0);
1507 sub_prog_node.activate();
1508 defer sub_prog_node.end();
1509
1506 // ensure the error names table is populated when an error name is referenced1510 // ensure the error names table is populated when an error name is referenced
1507 try self.populateErrorNameTable();1511 try self.populateErrorNameTable();
15081512
...@@ -2028,7 +2032,7 @@ fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void {...@@ -2028,7 +2032,7 @@ fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void {
2028 }2032 }
2029}2033}
20302034
2031fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {2035fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
2032 const tracy = trace(@src());2036 const tracy = trace(@src());
2033 defer tracy.end();2037 defer tracy.end();
20342038
...@@ -2060,7 +2064,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -2060,7 +2064,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
2060 }2064 }
2061 }2065 }
20622066
2063 try self.flushModule(comp);2067 try self.flushModule(comp, prog_node);
20642068
2065 if (fs.path.dirname(full_out_path)) |dirname| {2069 if (fs.path.dirname(full_out_path)) |dirname| {
2066 break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? });2070 break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? });
...@@ -2069,6 +2073,11 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -2069,6 +2073,11 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
2069 }2073 }
2070 } else null;2074 } else null;
20712075
2076 var sub_prog_node = prog_node.start("LLD Link", 0);
2077 sub_prog_node.activate();
2078 sub_prog_node.context.refresh();
2079 defer sub_prog_node.end();
2080
2072 const is_obj = self.base.options.output_mode == .Obj;2081 const is_obj = self.base.options.output_mode == .Obj;
20732082
2074 const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt and !is_obj)2083 const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt and !is_obj)