diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-03-11 19:31:29 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-03-11 19:38:07 -0700 |
| commit | 55ba335e0ffc2af76bf0743d98f5a959ccce0409 (patch) | |
| tree | f9f705b5f33d0d54c52cdee9e38e40424ab9fd52 /src/Compilation.zig | |
| parent | 2ee3cc453c4cefa3519f6a6238d4721364d829ae (diff) | |
| download | zig-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.zig | 134 |
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, |
