diff options
Diffstat (limited to 'src/Compilation.zig')
| -rw-r--r-- | src/Compilation.zig | 144 |
1 files changed, 95 insertions, 49 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index ce6ab0fa76..c7323b91f9 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1,6 +1,7 @@ const Compilation = @This(); const std = @import("std"); +const builtin = @import("builtin"); const mem = std.mem; const Allocator = std.mem.Allocator; const assert = std.debug.assert; @@ -13,7 +14,7 @@ const target_util = @import("target.zig"); const Package = @import("Package.zig"); const link = @import("link.zig"); const trace = @import("tracy.zig").trace; -const liveness = @import("liveness.zig"); +const Liveness = @import("Liveness.zig"); const build_options = @import("build_options"); const LibCInstallation = @import("libc_installation.zig").LibCInstallation; const glibc = @import("glibc.zig"); @@ -148,7 +149,7 @@ emit_docs: ?EmitLoc, work_queue_wait_group: WaitGroup, astgen_wait_group: WaitGroup, -pub const InnerError = Module.InnerError; +pub const SemaError = Module.SemaError; pub const CRTFile = struct { lock: Cache.Lock, @@ -168,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. @@ -1927,6 +1930,7 @@ pub fn getCompileLogOutput(self: *Compilation) []const u8 { } pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemory }!void { + const gpa = self.gpa; // If the terminal is dumb, we dont want to show the user all the // output. var progress: std.Progress = .{ .dont_print_on_dumb = true }; @@ -2008,33 +2012,6 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor @panic("sadly stage2 is omitted from this build to save memory on the CI server"); const module = self.bin_file.options.module.?; assert(decl.has_tv); - if (decl.val.castTag(.function)) |payload| { - const func = payload.data; - switch (func.state) { - .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 - .sema_failure, .dependency_failure => continue, - .success => {}, - } - // Here we tack on additional allocations to the Decl's arena. The allocations - // are lifetime annotations in the ZIR. - var decl_arena = decl.value_arena.?.promote(module.gpa); - defer decl.value_arena.?.* = decl_arena.state; - log.debug("analyze liveness of {s}", .{decl.name}); - try liveness.analyze(module.gpa, &decl_arena.allocator, func.body); - - if (std.builtin.mode == .Debug and self.verbose_air) { - func.dump(module.*); - } - } - assert(decl.ty.hasCodeGenBits()); self.bin_file.updateDecl(module, decl) catch |err| switch (err) { @@ -2044,9 +2021,74 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor continue; }, else => { - try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.count() + 1); + 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; + }, + }; + }, + }, + .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, decl.namespace.file_scope.zir, 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( - module.gpa, + gpa, decl.srcLoc(), "unable to codegen: {s}", .{@errorName(err)}, @@ -2055,6 +2097,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor continue; }, }; + continue; }, }, .emit_h_decl => |decl| switch (decl.analysis) { @@ -2075,7 +2118,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor @panic("sadly stage2 is omitted from this build to save memory on the CI server"); const module = self.bin_file.options.module.?; const emit_h = module.emit_h.?; - _ = try emit_h.decl_table.getOrPut(module.gpa, decl); + _ = try emit_h.decl_table.getOrPut(gpa, decl); const decl_emit_h = decl.getEmitH(module); const fwd_decl = &decl_emit_h.fwd_decl; fwd_decl.shrinkRetainingCapacity(0); @@ -2084,7 +2127,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor .module = module, .error_msg = null, .decl = decl, - .fwd_decl = fwd_decl.toManaged(module.gpa), + .fwd_decl = fwd_decl.toManaged(gpa), // we don't want to emit optionals and error unions to headers since they have no ABI .typedefs = undefined, }; @@ -2092,14 +2135,14 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor c_codegen.genHeader(&dg) catch |err| switch (err) { error.AnalysisFail => { - try emit_h.failed_decls.put(module.gpa, decl, dg.error_msg.?); + try emit_h.failed_decls.put(gpa, decl, dg.error_msg.?); continue; }, else => |e| return e, }; fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); - fwd_decl.shrinkAndFree(module.gpa, fwd_decl.items.len); + fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len); }, }, .analyze_decl => |decl| { @@ -2116,9 +2159,9 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor @panic("sadly stage2 is omitted from this build to save memory on the CI server"); const module = self.bin_file.options.module.?; self.bin_file.updateDeclLineNumber(module, decl) catch |err| { - try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.count() + 1); + try module.failed_decls.ensureUnusedCapacity(gpa, 1); module.failed_decls.putAssumeCapacityNoClobber(decl, try Module.ErrorMsg.create( - module.gpa, + gpa, decl.srcLoc(), "unable to update line number: {s}", .{@errorName(err)}, @@ -2320,7 +2363,7 @@ const AstGenSrc = union(enum) { root, import: struct { importing_file: *Module.Scope.File, - import_inst: Zir.Inst.Index, + import_tok: std.zig.ast.TokenIndex, }, }; @@ -2357,11 +2400,15 @@ fn workerAstGenFile( assert(file.zir_loaded); const imports_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.imports)]; if (imports_index != 0) { - const imports_len = file.zir.extra[imports_index]; + const extra = file.zir.extraData(Zir.Inst.Imports, imports_index); + var import_i: u32 = 0; + var extra_index = extra.end; - for (file.zir.extra[imports_index + 1 ..][0..imports_len]) |import_inst| { - const inst_data = file.zir.instructions.items(.data)[import_inst].str_tok; - const import_path = inst_data.get(file.zir); + while (import_i < extra.data.imports_len) : (import_i += 1) { + const item = file.zir.extraData(Zir.Inst.Imports.Item, extra_index); + extra_index = item.end; + + const import_path = file.zir.nullTerminatedString(item.data.name); const import_result = blk: { const lock = comp.mutex.acquire(); @@ -2375,7 +2422,7 @@ fn workerAstGenFile( }); const sub_src: AstGenSrc = .{ .import = .{ .importing_file = file, - .import_inst = import_inst, + .import_tok = item.data.token, } }; wg.start(); comp.thread_pool.spawn(workerAstGenFile, .{ @@ -2607,12 +2654,11 @@ fn reportRetryableAstGenError( }, .import => |info| blk: { const importing_file = info.importing_file; - const import_inst = info.import_inst; - const inst_data = importing_file.zir.instructions.items(.data)[import_inst].str_tok; + break :blk .{ .file_scope = importing_file, .parent_decl_node = 0, - .lazy = .{ .token_offset = inst_data.src_tok }, + .lazy = .{ .token_abs = info.import_tok }, }; }, }; @@ -3149,7 +3195,7 @@ pub fn addCCArgs( try argv.appendSlice(comp.clang_argv); } -fn failCObj(comp: *Compilation, c_object: *CObject, comptime format: []const u8, args: anytype) InnerError { +fn failCObj(comp: *Compilation, c_object: *CObject, comptime format: []const u8, args: anytype) SemaError { @setCold(true); const err_msg = blk: { const msg = try std.fmt.allocPrint(comp.gpa, format, args); @@ -3170,7 +3216,7 @@ fn failCObjWithOwnedErrorMsg( comp: *Compilation, c_object: *CObject, err_msg: *CObject.ErrorMsg, -) InnerError { +) SemaError { @setCold(true); { const lock = comp.mutex.acquire(); |
