Skip to content

Commit

Permalink
stage2: expose progress bar API to linker backends
Browse files Browse the repository at this point in the history
This gives us insight as to what is happening when we are waiting for
things such as LLVM emit object and LLD linking.
  • Loading branch information
andrewrk committed Apr 17, 2022
1 parent 2aeaa1c commit a7c05c0
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 83 deletions.
30 changes: 16 additions & 14 deletions src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2084,7 +2084,13 @@ pub fn update(comp: *Compilation) !void {
}
}

try comp.performAllTheWork();
// If the terminal is dumb, we dont want to show the user all the output.
var progress: std.Progress = .{ .dont_print_on_dumb = true };
const main_progress_node = progress.start("", 0);
defer main_progress_node.end();
if (comp.color == .off) progress.terminal = null;

try comp.performAllTheWork(main_progress_node);

if (!use_stage1) {
if (comp.bin_file.options.module) |module| {
Expand Down Expand Up @@ -2158,9 +2164,9 @@ pub fn update(comp: *Compilation) !void {
.path = dir_path,
};

try comp.flush();
try comp.flush(main_progress_node);
} else {
try comp.flush();
try comp.flush(main_progress_node);
}

// Failure here only means an unnecessary cache miss.
Expand All @@ -2171,7 +2177,7 @@ pub fn update(comp: *Compilation) !void {
assert(comp.bin_file.lock == null);
comp.bin_file.lock = man.toOwnedLock();
} else {
try comp.flush();
try comp.flush(main_progress_node);
}

// Unload all source files to save memory.
Expand All @@ -2188,8 +2194,8 @@ pub fn update(comp: *Compilation) !void {
}
}

fn flush(comp: *Compilation) !void {
try comp.bin_file.flush(comp); // This is needed before reading the error flags.
fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void {
try comp.bin_file.flush(comp, prog_node); // This is needed before reading the error flags.
comp.link_error_flags = comp.bin_file.errorFlags();

const use_stage1 = build_options.omit_stage2 or
Expand Down Expand Up @@ -2590,14 +2596,10 @@ pub fn getCompileLogOutput(self: *Compilation) []const u8 {
return module.compile_log_text.items;
}

pub fn performAllTheWork(comp: *Compilation) error{ TimerUnsupported, OutOfMemory }!void {
// If the terminal is dumb, we dont want to show the user all the
// output.
var progress: std.Progress = .{ .dont_print_on_dumb = true };
var main_progress_node = progress.start("", 0);
defer main_progress_node.end();
if (comp.color == .off) progress.terminal = null;

pub fn performAllTheWork(
comp: *Compilation,
main_progress_node: *std.Progress.Node,
) error{ TimerUnsupported, OutOfMemory }!void {
// Here we queue up all the AstGen tasks first, followed by C object compilation.
// We wait until the AstGen tasks are all completed before proceeding to the
// (at least for now) single-threaded main work queue. However, C object compilation
Expand Down
7 changes: 6 additions & 1 deletion src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,12 @@ pub const Object = struct {
_ = builder.buildRet(is_lt);
}

pub fn flushModule(self: *Object, comp: *Compilation) !void {
pub fn flushModule(self: *Object, comp: *Compilation, prog_node: *std.Progress.Node) !void {
var sub_prog_node = prog_node.start("LLVM Emit Object", 0);
sub_prog_node.activate();
sub_prog_node.context.refresh();
defer sub_prog_node.end();

try self.genErrorNameTable(comp);
try self.genCmpLtErrorsLenFunction(comp);

Expand Down
44 changes: 22 additions & 22 deletions src/link.zig
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ 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) !void {
pub fn flush(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) !void {
if (comp.clang_preprocessor_mode == .yes) {
const emit = base.options.emit orelse return; // -fno-emit-bin
// TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)
Expand All @@ -591,32 +591,32 @@ pub const File = struct {

const use_lld = build_options.have_llvm and base.options.use_lld;
if (use_lld and base.options.output_mode == .Lib and base.options.link_mode == .Static) {
return base.linkAsArchive(comp);
return base.linkAsArchive(comp, prog_node);
}
switch (base.tag) {
.coff => return @fieldParentPtr(Coff, "base", base).flush(comp),
.elf => return @fieldParentPtr(Elf, "base", base).flush(comp),
.macho => return @fieldParentPtr(MachO, "base", base).flush(comp),
.c => return @fieldParentPtr(C, "base", base).flush(comp),
.wasm => return @fieldParentPtr(Wasm, "base", base).flush(comp),
.spirv => return @fieldParentPtr(SpirV, "base", base).flush(comp),
.plan9 => return @fieldParentPtr(Plan9, "base", base).flush(comp),
.nvptx => return @fieldParentPtr(NvPtx, "base", base).flush(comp),
.coff => return @fieldParentPtr(Coff, "base", base).flush(comp, prog_node),
.elf => return @fieldParentPtr(Elf, "base", base).flush(comp, prog_node),
.macho => return @fieldParentPtr(MachO, "base", base).flush(comp, prog_node),
.c => return @fieldParentPtr(C, "base", base).flush(comp, prog_node),
.wasm => return @fieldParentPtr(Wasm, "base", base).flush(comp, prog_node),
.spirv => return @fieldParentPtr(SpirV, "base", base).flush(comp, prog_node),
.plan9 => return @fieldParentPtr(Plan9, "base", base).flush(comp, prog_node),
.nvptx => return @fieldParentPtr(NvPtx, "base", base).flush(comp, prog_node),
}
}

/// Commit pending changes and write headers. Works based on `effectiveOutputMode`
/// rather than final output mode.
pub fn flushModule(base: *File, comp: *Compilation) !void {
pub fn flushModule(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) !void {
switch (base.tag) {
.coff => return @fieldParentPtr(Coff, "base", base).flushModule(comp),
.elf => return @fieldParentPtr(Elf, "base", base).flushModule(comp),
.macho => return @fieldParentPtr(MachO, "base", base).flushModule(comp),
.c => return @fieldParentPtr(C, "base", base).flushModule(comp),
.wasm => return @fieldParentPtr(Wasm, "base", base).flushModule(comp),
.spirv => return @fieldParentPtr(SpirV, "base", base).flushModule(comp),
.plan9 => return @fieldParentPtr(Plan9, "base", base).flushModule(comp),
.nvptx => return @fieldParentPtr(NvPtx, "base", base).flushModule(comp),
.coff => return @fieldParentPtr(Coff, "base", base).flushModule(comp, prog_node),
.elf => return @fieldParentPtr(Elf, "base", base).flushModule(comp, prog_node),
.macho => return @fieldParentPtr(MachO, "base", base).flushModule(comp, prog_node),
.c => return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node),
.wasm => return @fieldParentPtr(Wasm, "base", base).flushModule(comp, prog_node),
.spirv => return @fieldParentPtr(SpirV, "base", base).flushModule(comp, prog_node),
.plan9 => return @fieldParentPtr(Plan9, "base", base).flushModule(comp, prog_node),
.nvptx => return @fieldParentPtr(NvPtx, "base", base).flushModule(comp, prog_node),
}
}

Expand Down Expand Up @@ -754,7 +754,7 @@ pub const File = struct {
}
}

pub fn linkAsArchive(base: *File, comp: *Compilation) !void {
pub fn linkAsArchive(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();

Expand Down Expand Up @@ -787,9 +787,9 @@ pub const File = struct {
}
}
if (base.options.object_format == .macho) {
try base.cast(MachO).?.flushObject(comp);
try base.cast(MachO).?.flushObject(comp, prog_node);
} else {
try base.flushModule(comp);
try base.flushModule(comp, prog_node);
}
break :blk try fs.path.join(arena, &.{
fs.path.dirname(full_out_path_z).?, base.intermediary_basename.?,
Expand Down
10 changes: 7 additions & 3 deletions src/link/C.zig
Original file line number Diff line number Diff line change
Expand Up @@ -235,14 +235,18 @@ pub fn updateDeclLineNumber(self: *C, module: *Module, decl: *Module.Decl) !void
_ = decl;
}

pub fn flush(self: *C, comp: *Compilation) !void {
return self.flushModule(comp);
pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void {
return self.flushModule(comp, prog_node);
}

pub fn flushModule(self: *C, comp: *Compilation) !void {
pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();

var sub_prog_node = prog_node.start("Flush Module", 0);
sub_prog_node.activate();
defer sub_prog_node.end();

const gpa = comp.gpa;
const module = self.base.options.module.?;

Expand Down
25 changes: 17 additions & 8 deletions src/link/Coff.zig
Original file line number Diff line number Diff line change
Expand Up @@ -829,36 +829,40 @@ pub fn updateDeclExports(
}
}

pub fn flush(self: *Coff, comp: *Compilation) !void {
pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {
if (self.base.options.emit == null) {
if (build_options.have_llvm) {
if (self.llvm_object) |llvm_object| {
return try llvm_object.flushModule(comp);
return try llvm_object.flushModule(comp, prog_node);
}
}
return;
}
if (build_options.have_llvm and self.base.options.use_lld) {
return self.linkWithLLD(comp);
return self.linkWithLLD(comp, prog_node);
} else {
switch (self.base.options.effectiveOutputMode()) {
.Exe, .Obj => {},
.Lib => return error.TODOImplementWritingLibFiles,
}
return self.flushModule(comp);
return self.flushModule(comp, prog_node);
}
}

pub fn flushModule(self: *Coff, comp: *Compilation) !void {
pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();

if (build_options.have_llvm) {
if (self.llvm_object) |llvm_object| {
return try llvm_object.flushModule(comp);
return try llvm_object.flushModule(comp, prog_node);
}
}

var sub_prog_node = prog_node.start("COFF Flush", 0);
sub_prog_node.activate();
defer sub_prog_node.end();

if (self.text_section_size_dirty) {
// Write the new raw size in the .text header
var buf: [4]u8 = undefined;
Expand Down Expand Up @@ -892,7 +896,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
}
}

fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();

Expand Down Expand Up @@ -924,7 +928,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
}
}

try self.flushModule(comp);
try self.flushModule(comp, prog_node);

if (fs.path.dirname(full_out_path)) |dirname| {
break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? });
Expand All @@ -933,6 +937,11 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
}
} else null;

var sub_prog_node = prog_node.start("LLD Link", 0);
sub_prog_node.activate();
sub_prog_node.context.refresh();
defer sub_prog_node.end();

const is_lib = self.base.options.output_mode == .Lib;
const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;
const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
Expand Down
25 changes: 17 additions & 8 deletions src/link/Elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -929,35 +929,39 @@ pub fn populateMissingMetadata(self: *Elf) !void {
}
}

pub fn flush(self: *Elf, comp: *Compilation) !void {
pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
if (self.base.options.emit == null) {
if (build_options.have_llvm) {
if (self.llvm_object) |llvm_object| {
return try llvm_object.flushModule(comp);
return try llvm_object.flushModule(comp, prog_node);
}
}
return;
}
const use_lld = build_options.have_llvm and self.base.options.use_lld;
if (use_lld) {
return self.linkWithLLD(comp);
return self.linkWithLLD(comp, prog_node);
}
switch (self.base.options.output_mode) {
.Exe, .Obj => return self.flushModule(comp),
.Exe, .Obj => return self.flushModule(comp, prog_node),
.Lib => return error.TODOImplementWritingLibFiles,
}
}

pub fn flushModule(self: *Elf, comp: *Compilation) !void {
pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();

if (build_options.have_llvm) {
if (self.llvm_object) |llvm_object| {
return try llvm_object.flushModule(comp);
return try llvm_object.flushModule(comp, prog_node);
}
}

var sub_prog_node = prog_node.start("ELF Flush", 0);
sub_prog_node.activate();
defer sub_prog_node.end();

// TODO This linker code currently assumes there is only 1 compilation unit and it
// corresponds to the Zig source code.
const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
Expand Down Expand Up @@ -1204,7 +1208,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
assert(!self.debug_strtab_dirty);
}

fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();

Expand Down Expand Up @@ -1236,7 +1240,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
}
}

try self.flushModule(comp);
try self.flushModule(comp, prog_node);

if (fs.path.dirname(full_out_path)) |dirname| {
break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? });
Expand All @@ -1245,6 +1249,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
}
} else null;

var sub_prog_node = prog_node.start("LLD Link", 0);
sub_prog_node.activate();
sub_prog_node.context.refresh();
defer sub_prog_node.end();

const is_obj = self.base.options.output_mode == .Obj;
const is_lib = self.base.options.output_mode == .Lib;
const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;
Expand Down
Loading

0 comments on commit a7c05c0

Please sign in to comment.