aboutsummaryrefslogtreecommitdiff
path: root/src/Compilation.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Compilation.zig')
-rw-r--r--src/Compilation.zig144
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();