From 8c9ac4db978c80246b4872c899b1618b1b195ec2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Jan 2021 22:51:01 -0700 Subject: stage2: implement error notes and regress -femit-zir * Implement error notes - note: other symbol exported here - note: previous else prong is here - note: previous '_' prong is here * Add Compilation.CObject.ErrorMsg. This object properly converts to AllErrors.Message when the time comes. * Add Compilation.CObject.failure_retryable. Properly handles out-of-memory and other transient failures. * Introduce Module.SrcLoc which has not only a byte offset but also references the file which the byte offset applies to. * Scope.Block now contains both a pointer to the "owner" Decl and the "source" Decl. As an example, during inline function call, the "owner" will be the Decl of the caller and the "source" will be the Decl of the callee. * Module.ErrorMsg now sports a `file_scope` field so that notes can refer to source locations in a file other than the parent error message. * Some instances where a `*Scope` was stored, now store a `*Scope.Container`. * Some methods in the `Scope` namespace were moved to the more specific type, since there was only an implementation for one particular tag. - `removeDecl` moved to `Scope.Container` - `destroy` moved to `Scope.File` * Two kinds of Scope deleted: - zir_module - decl * astgen: properly use DeclVal / DeclRef. DeclVal was incorrectly changed to be a reference; this commit fixes it. Fewer ZIR instructions processed as a result. - declval_in_module is renamed to declval - previous declval ZIR instruction is deleted; it was only for .zir files. * Test harness: friendlier diagnostics when an unexpected set of errors is encountered. * zir_sema: fix analyzeInstBlockFlat by properly calling resolvingInst on the last zir instruction in the block. Compile log implementation: * Write to a buffer rather than directly to stderr. * Only keep track of 1 callsite per Decl. * No longer mutate the ZIR Inst struct data. * "Compile log statement found" errors are only emitted when there are no other compile errors. -femit-zir and support for .zir source files is regressed. If we wanted to support this again, outputting .zir would need to be done as yet another backend rather than in the haphazard way it was previously implemented. For parsing .zir, it was implemented previously in a way that was not helpful for debugging. We need tighter integration with the test harness for it to be useful; so clearly a rewrite is needed. Given that a rewrite is needed, and it was getting in the way of progress and organization of the rest of stage2, I regressed the feature. --- src/codegen/c.zig | 7 +++++-- src/codegen/llvm.zig | 13 +++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 8c85f482fd..b26f753757 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -114,10 +114,13 @@ pub const DeclGen = struct { module: *Module, decl: *Decl, fwd_decl: std.ArrayList(u8), - error_msg: ?*Compilation.ErrorMsg, + error_msg: ?*Module.ErrorMsg, fn fail(dg: *DeclGen, src: usize, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { - dg.error_msg = try Compilation.ErrorMsg.create(dg.module.gpa, src, format, args); + dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, .{ + .file_scope = dg.decl.getFileScope(), + .byte_offset = src, + }, format, args); return error.AnalysisFail; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 5d753c41cb..1edd466d54 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -148,7 +148,7 @@ pub const LLVMIRModule = struct { object_path: []const u8, gpa: *Allocator, - err_msg: ?*Compilation.ErrorMsg = null, + err_msg: ?*Module.ErrorMsg = null, // TODO: The fields below should really move into a different struct, // because they are only valid when generating a function @@ -177,6 +177,8 @@ pub const LLVMIRModule = struct { break_vals: *BreakValues, }) = .{}, + src_loc: Module.SrcLoc, + const BreakBasicBlocks = std.ArrayListUnmanaged(*const llvm.BasicBlock); const BreakValues = std.ArrayListUnmanaged(*const llvm.Value); @@ -254,6 +256,8 @@ pub const LLVMIRModule = struct { .builder = builder, .object_path = object_path, .gpa = gpa, + // TODO move this field into a struct that is only instantiated per gen() call + .src_loc = undefined, }; return self; } @@ -335,6 +339,8 @@ pub const LLVMIRModule = struct { const typed_value = decl.typed_value.most_recent.typed_value; const src = decl.src(); + self.src_loc = decl.srcLoc(); + log.debug("gen: {s} type: {}, value: {}", .{ decl.name, typed_value.ty, typed_value.val }); if (typed_value.val.castTag(.function)) |func_payload| { @@ -853,7 +859,10 @@ pub const LLVMIRModule = struct { pub fn fail(self: *LLVMIRModule, src: usize, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } { @setCold(true); assert(self.err_msg == null); - self.err_msg = try Compilation.ErrorMsg.create(self.gpa, src, format, args); + self.err_msg = try Module.ErrorMsg.create(self.gpa, .{ + .file_scope = self.src_loc.file_scope, + .byte_offset = src, + }, format, args); return error.CodegenFail; } }; -- cgit v1.2.3