aboutsummaryrefslogtreecommitdiff
path: root/src/Compilation.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-03-11 19:31:29 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-11 19:38:07 -0700
commit55ba335e0ffc2af76bf0743d98f5a959ccce0409 (patch)
treef9f705b5f33d0d54c52cdee9e38e40424ab9fd52 /src/Compilation.zig
parent2ee3cc453c4cefa3519f6a6238d4721364d829ae (diff)
downloadzig-55ba335e0ffc2af76bf0743d98f5a959ccce0409.tar.gz
zig-55ba335e0ffc2af76bf0743d98f5a959ccce0409.zip
Sema: fix resolution of inferred error sets
Introduce `Module.ensureFuncBodyAnalyzed` and corresponding `Sema` function. This mirrors `ensureDeclAnalyzed` except also waits until the function body has been semantically analyzed, meaning that inferred error sets will have been populated. Resolving error sets can now emit a "unable to resolve inferred error set" error instead of producing an incorrect error set type. Resolving error sets now calls `ensureFuncBodyAnalyzed`. Closes #11046. `coerceInMemoryAllowedErrorSets` now does a lot more work to avoid resolving an inferred error set if possible. Same with `wrapErrorUnionSet`. Inferred error set types no longer check the `func` field to determine if they are equal. That was incorrect because an inline or comptime function call produces a unique error set which has the same `*Module.Fn` value for this field. Instead we use the `*Module.Fn.InferredErrorSet` pointers to test equality of inferred error sets.
Diffstat (limited to 'src/Compilation.zig')
-rw-r--r--src/Compilation.zig134
1 files changed, 28 insertions, 106 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index fa2e4ca68b..5e02d8dba2 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -15,7 +15,6 @@ const Package = @import("Package.zig");
const link = @import("link.zig");
const tracy = @import("tracy.zig");
const trace = tracy.trace;
-const Liveness = @import("Liveness.zig");
const build_options = @import("build_options");
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
const glibc = @import("glibc.zig");
@@ -2702,12 +2701,12 @@ fn processOneJob(comp: *Compilation, job: Job, main_progress_node: *std.Progress
=> return,
.complete, .codegen_failure_retryable => {
- const named_frame = tracy.namedFrame("codegen_decl");
- defer named_frame.end();
-
if (build_options.omit_stage2)
@panic("sadly stage2 is omitted from this build to save memory on the CI server");
+ const named_frame = tracy.namedFrame("codegen_decl");
+ defer named_frame.end();
+
const module = comp.bin_file.options.module.?;
assert(decl.has_tv);
@@ -2722,100 +2721,18 @@ fn processOneJob(comp: *Compilation, job: Job, main_progress_node: *std.Progress
return;
},
},
- .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,
- => return,
-
- .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 => return,
- .queued => {},
- .in_progress => unreachable,
- .inline_only => unreachable, // don't queue work for this
- .success => unreachable, // don't queue it twice
- }
-
- const gpa = comp.gpa;
- const module = comp.bin_file.options.module.?;
- const decl = func.owner_decl;
-
- var tmp_arena = std.heap.ArenaAllocator.init(gpa);
- defer tmp_arena.deinit();
- const sema_arena = tmp_arena.allocator();
-
- const sema_frame = tracy.namedFrame("sema");
- var sema_frame_ended = false;
- errdefer if (!sema_frame_ended) sema_frame.end();
-
- var air = module.analyzeFnBody(decl, func, sema_arena) catch |err| switch (err) {
- error.AnalysisFail => {
- if (func.state == .in_progress) {
- // If this decl caused the compile error, the analysis field would
- // be changed to indicate it was this Decl's fault. Because this
- // did not happen, we infer here that it was a dependency failure.
- func.state = .dependency_failure;
- }
- return;
- },
- error.OutOfMemory => return error.OutOfMemory,
- };
- defer air.deinit(gpa);
-
- sema_frame.end();
- sema_frame_ended = true;
-
- if (comp.bin_file.options.emit == null) return;
-
- const liveness_frame = tracy.namedFrame("liveness");
- var liveness_frame_ended = false;
- errdefer if (!liveness_frame_ended) liveness_frame.end();
-
- log.debug("analyze liveness of {s}", .{decl.name});
- var liveness = try Liveness.analyze(gpa, air);
- defer liveness.deinit(gpa);
-
- liveness_frame.end();
- liveness_frame_ended = true;
-
- if (builtin.mode == .Debug and comp.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\n", .{decl.name});
- }
+ .codegen_func => |func| {
+ if (build_options.omit_stage2)
+ @panic("sadly stage2 is omitted from this build to save memory on the CI server");
- const named_frame = tracy.namedFrame("codegen");
- defer named_frame.end();
+ const named_frame = tracy.namedFrame("codegen_func");
+ defer named_frame.end();
- comp.bin_file.updateFunc(module, func, air, liveness) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.AnalysisFail => {
- decl.analysis = .codegen_failure;
- return;
- },
- 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;
- return;
- },
- };
- return;
- },
+ const module = comp.bin_file.options.module.?;
+ module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.AnalysisFail => return,
+ };
},
.emit_h_decl => |decl| switch (decl.analysis) {
.unreferenced => unreachable,
@@ -2831,11 +2748,12 @@ fn processOneJob(comp: *Compilation, job: Job, main_progress_node: *std.Progress
// emit-h only requires semantic analysis of the Decl to be complete,
// it does not depend on machine code generation to succeed.
.codegen_failure, .codegen_failure_retryable, .complete => {
+ if (build_options.omit_stage2)
+ @panic("sadly stage2 is omitted from this build to save memory on the CI server");
+
const named_frame = tracy.namedFrame("emit_h_decl");
defer named_frame.end();
- if (build_options.omit_stage2)
- @panic("sadly stage2 is omitted from this build to save memory on the CI server");
const gpa = comp.gpa;
const module = comp.bin_file.options.module.?;
const emit_h = module.emit_h.?;
@@ -2871,11 +2789,12 @@ fn processOneJob(comp: *Compilation, job: Job, main_progress_node: *std.Progress
},
},
.analyze_decl => |decl| {
+ if (build_options.omit_stage2)
+ @panic("sadly stage2 is omitted from this build to save memory on the CI server");
+
const named_frame = tracy.namedFrame("analyze_decl");
defer named_frame.end();
- if (build_options.omit_stage2)
- @panic("sadly stage2 is omitted from this build to save memory on the CI server");
const module = comp.bin_file.options.module.?;
module.ensureDeclAnalyzed(decl) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
@@ -2883,11 +2802,12 @@ fn processOneJob(comp: *Compilation, job: Job, main_progress_node: *std.Progress
};
},
.update_embed_file => |embed_file| {
+ if (build_options.omit_stage2)
+ @panic("sadly stage2 is omitted from this build to save memory on the CI server");
+
const named_frame = tracy.namedFrame("update_embed_file");
defer named_frame.end();
- if (build_options.omit_stage2)
- @panic("sadly stage2 is omitted from this build to save memory on the CI server");
const module = comp.bin_file.options.module.?;
module.updateEmbedFile(embed_file) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
@@ -2895,11 +2815,12 @@ fn processOneJob(comp: *Compilation, job: Job, main_progress_node: *std.Progress
};
},
.update_line_number => |decl| {
+ if (build_options.omit_stage2)
+ @panic("sadly stage2 is omitted from this build to save memory on the CI server");
+
const named_frame = tracy.namedFrame("update_line_number");
defer named_frame.end();
- if (build_options.omit_stage2)
- @panic("sadly stage2 is omitted from this build to save memory on the CI server");
const gpa = comp.gpa;
const module = comp.bin_file.options.module.?;
comp.bin_file.updateDeclLineNumber(module, decl) catch |err| {
@@ -2914,11 +2835,12 @@ fn processOneJob(comp: *Compilation, job: Job, main_progress_node: *std.Progress
};
},
.analyze_pkg => |pkg| {
+ if (build_options.omit_stage2)
+ @panic("sadly stage2 is omitted from this build to save memory on the CI server");
+
const named_frame = tracy.namedFrame("analyze_pkg");
defer named_frame.end();
- if (build_options.omit_stage2)
- @panic("sadly stage2 is omitted from this build to save memory on the CI server");
const module = comp.bin_file.options.module.?;
module.semaPkg(pkg) catch |err| switch (err) {
error.CurrentWorkingDirectoryUnlinked,