aboutsummaryrefslogtreecommitdiff
path: root/src/Compilation.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-07-20 15:22:37 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-07-20 15:22:37 -0700
commitfe14e339458a578657f3890f00d654a15c84422c (patch)
tree0b53177c9f8b84dbfbd67308ae06784f87387ee2 /src/Compilation.zig
parenta97e5e119afb80e0d6d047682b8301bab9423078 (diff)
downloadzig-fe14e339458a578657f3890f00d654a15c84422c.tar.gz
zig-fe14e339458a578657f3890f00d654a15c84422c.zip
stage2: separate work queue item for functions than decls
Previously we had codegen_decl for both constant values as well as function bodies. A recent commit updated the linker backends to add updateFunc as a separate function than updateDecl, and now this commit does the same with work queue tasks. The frontend now distinguishes between function pointers and function bodies.
Diffstat (limited to 'src/Compilation.zig')
-rw-r--r--src/Compilation.zig158
1 files changed, 114 insertions, 44 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 50d1f5760e..ea484c2d15 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -169,8 +169,10 @@ pub const CSourceFile = struct {
};
const Job = union(enum) {
- /// Write the machine code for a Decl to the output file.
+ /// Write the constant value for a Decl to the output file.
codegen_decl: *Module.Decl,
+ /// Write the machine code for a function to the output file.
+ codegen_func: *Module.Fn,
/// Render the .h file snippet for the Decl.
emit_h_decl: *Module.Decl,
/// The Decl needs to be analyzed and possibly export itself.
@@ -2006,54 +2008,56 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
const module = self.bin_file.options.module.?;
assert(decl.has_tv);
if (decl.val.castTag(.function)) |payload| {
- const func = payload.data;
+ if (decl.owns_tv) {
+ const func = payload.data;
+
+ var air = switch (func.state) {
+ .sema_failure, .dependency_failure => continue,
+ .queued => module.analyzeFnBody(decl, func) catch |err| switch (err) {
+ error.AnalysisFail => {
+ assert(func.state != .in_progress);
+ continue;
+ },
+ error.OutOfMemory => return error.OutOfMemory,
+ },
+ .in_progress => unreachable,
+ .inline_only => unreachable, // don't queue work for this
+ .success => unreachable, // don't queue it twice
+ };
+ defer air.deinit(gpa);
+
+ log.debug("analyze liveness of {s}", .{decl.name});
+ var liveness = try Liveness.analyze(gpa, air, decl.namespace.file_scope.zir);
+ defer liveness.deinit(gpa);
+
+ if (builtin.mode == .Debug and self.verbose_air) {
+ std.debug.print("# Begin Function AIR: {s}:\n", .{decl.name});
+ @import("print_air.zig").dump(gpa, air, liveness);
+ std.debug.print("# End Function AIR: {s}:\n", .{decl.name});
+ }
- var air = switch (func.state) {
- .queued => module.analyzeFnBody(decl, func) catch |err| switch (err) {
+ assert(decl.ty.hasCodeGenBits());
+
+ self.bin_file.updateFunc(module, func, air, liveness) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
error.AnalysisFail => {
- assert(func.state != .in_progress);
+ decl.analysis = .codegen_failure;
continue;
},
- error.OutOfMemory => return error.OutOfMemory,
- },
- .in_progress => unreachable,
- .inline_only => unreachable, // don't queue work for this
- .sema_failure, .dependency_failure => continue,
- .success => unreachable, // don't queue it twice
- };
- defer air.deinit(gpa);
-
- log.debug("analyze liveness of {s}", .{decl.name});
- var liveness = try Liveness.analyze(gpa, air, decl.namespace.file_scope.zir);
- defer liveness.deinit(gpa);
-
- if (builtin.mode == .Debug and self.verbose_air) {
- std.debug.print("# Begin Function AIR: {s}:\n", .{decl.name});
- @import("print_air.zig").dump(gpa, air, liveness);
- std.debug.print("# End Function AIR: {s}:\n", .{decl.name});
+ else => {
+ try module.failed_decls.ensureUnusedCapacity(gpa, 1);
+ module.failed_decls.putAssumeCapacityNoClobber(decl, try Module.ErrorMsg.create(
+ gpa,
+ decl.srcLoc(),
+ "unable to codegen: {s}",
+ .{@errorName(err)},
+ ));
+ decl.analysis = .codegen_failure_retryable;
+ continue;
+ },
+ };
+ continue;
}
-
- assert(decl.ty.hasCodeGenBits());
-
- self.bin_file.updateFunc(module, func, air, liveness) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.AnalysisFail => {
- decl.analysis = .codegen_failure;
- continue;
- },
- else => {
- try module.failed_decls.ensureUnusedCapacity(gpa, 1);
- module.failed_decls.putAssumeCapacityNoClobber(decl, try Module.ErrorMsg.create(
- gpa,
- decl.srcLoc(),
- "unable to codegen: {s}",
- .{@errorName(err)},
- ));
- decl.analysis = .codegen_failure_retryable;
- continue;
- },
- };
- continue;
}
assert(decl.ty.hasCodeGenBits());
@@ -2078,6 +2082,72 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
};
},
},
+ .codegen_func => |func| switch (func.owner_decl.analysis) {
+ .unreferenced => unreachable,
+ .in_progress => unreachable,
+ .outdated => unreachable,
+
+ .file_failure,
+ .sema_failure,
+ .codegen_failure,
+ .dependency_failure,
+ .sema_failure_retryable,
+ => continue,
+
+ .complete, .codegen_failure_retryable => {
+ if (build_options.omit_stage2)
+ @panic("sadly stage2 is omitted from this build to save memory on the CI server");
+ switch (func.state) {
+ .sema_failure, .dependency_failure => continue,
+ .queued => {},
+ .in_progress => unreachable,
+ .inline_only => unreachable, // don't queue work for this
+ .success => unreachable, // don't queue it twice
+ }
+
+ const module = self.bin_file.options.module.?;
+ const decl = func.owner_decl;
+
+ var air = module.analyzeFnBody(decl, func) catch |err| switch (err) {
+ error.AnalysisFail => {
+ assert(func.state != .in_progress);
+ continue;
+ },
+ error.OutOfMemory => return error.OutOfMemory,
+ };
+ defer air.deinit(gpa);
+
+ log.debug("analyze liveness of {s}", .{decl.name});
+ var liveness = try Liveness.analyze(gpa, air, decl.namespace.file_scope.zir);
+ defer liveness.deinit(gpa);
+
+ if (builtin.mode == .Debug and self.verbose_air) {
+ std.debug.print("# Begin Function AIR: {s}:\n", .{decl.name});
+ @import("print_air.zig").dump(gpa, air, liveness);
+ std.debug.print("# End Function AIR: {s}:\n", .{decl.name});
+ }
+
+ self.bin_file.updateFunc(module, func, air, liveness) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.AnalysisFail => {
+ decl.analysis = .codegen_failure;
+ continue;
+ },
+ else => {
+ try module.failed_decls.ensureUnusedCapacity(gpa, 1);
+ module.failed_decls.putAssumeCapacityNoClobber(decl, try Module.ErrorMsg.create(
+ gpa,
+ decl.srcLoc(),
+ "unable to codegen: {s}",
+ .{@errorName(err)},
+ ));
+ decl.analysis = .codegen_failure_retryable;
+ continue;
+ },
+ };
+ continue;
+ },
+ },
.emit_h_decl => |decl| switch (decl.analysis) {
.unreferenced => unreachable,
.in_progress => unreachable,