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.zig | 166 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 87 insertions(+), 79 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index 709c91a635..9f2fbaab78 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -9,7 +9,7 @@ const TypedValue = @import("TypedValue.zig"); const link = @import("link.zig"); const Module = @import("Module.zig"); const Compilation = @import("Compilation.zig"); -const ErrorMsg = Compilation.ErrorMsg; +const ErrorMsg = Module.ErrorMsg; const Target = std.Target; const Allocator = mem.Allocator; const trace = @import("tracy.zig").trace; @@ -74,7 +74,7 @@ pub const DebugInfoOutput = union(enum) { pub fn generateSymbol( bin_file: *link.File, - src: usize, + src_loc: Module.SrcLoc, typed_value: TypedValue, code: *std.ArrayList(u8), debug_output: DebugInfoOutput, @@ -87,56 +87,56 @@ pub fn generateSymbol( switch (bin_file.options.target.cpu.arch) { .wasm32 => unreachable, // has its own code path .wasm64 => unreachable, // has its own code path - .arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, debug_output), - .armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, debug_output), - .aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, debug_output), - .aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, debug_output), - .aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code, debug_output), - .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code, debug_output), - .spu_2 => return Function(.spu_2).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code, debug_output), - .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code, debug_output), - //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code, debug_output), + .arm => return Function(.arm).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + .armeb => return Function(.armeb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + .aarch64 => return Function(.aarch64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + .aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + .aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.arc => return Function(.arc).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.avr => return Function(.avr).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.mips => return Function(.mips).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.mips64 => return Function(.mips64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.msp430 => return Function(.msp430).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.r600 => return Function(.r600).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.sparc => return Function(.sparc).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.s390x => return Function(.s390x).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + .spu_2 => return Function(.spu_2).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.tce => return Function(.tce).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.tcele => return Function(.tcele).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.thumb => return Function(.thumb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.i386 => return Function(.i386).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.xcore => return Function(.xcore).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.le32 => return Function(.le32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.le64 => return Function(.le64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.amdil => return Function(.amdil).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.hsail => return Function(.hsail).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.spir => return Function(.spir).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.spir64 => return Function(.spir64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.shave => return Function(.shave).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.lanai => return Function(.lanai).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), + //.ve => return Function(.ve).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."), } }, @@ -147,7 +147,7 @@ pub fn generateSymbol( try code.ensureCapacity(code.items.len + payload.data.len + 1); code.appendSliceAssumeCapacity(payload.data); const prev_len = code.items.len; - switch (try generateSymbol(bin_file, src, .{ + switch (try generateSymbol(bin_file, src_loc, .{ .ty = typed_value.ty.elemType(), .val = sentinel, }, code, debug_output)) { @@ -165,7 +165,7 @@ pub fn generateSymbol( return Result{ .fail = try ErrorMsg.create( bin_file.allocator, - src, + src_loc, "TODO implement generateSymbol for more kinds of arrays", .{}, ), @@ -200,7 +200,7 @@ pub fn generateSymbol( return Result{ .fail = try ErrorMsg.create( bin_file.allocator, - src, + src_loc, "TODO implement generateSymbol for pointer {}", .{typed_value.val}, ), @@ -217,7 +217,7 @@ pub fn generateSymbol( return Result{ .fail = try ErrorMsg.create( bin_file.allocator, - src, + src_loc, "TODO implement generateSymbol for int type '{}'", .{typed_value.ty}, ), @@ -227,7 +227,7 @@ pub fn generateSymbol( return Result{ .fail = try ErrorMsg.create( bin_file.allocator, - src, + src_loc, "TODO implement generateSymbol for type '{s}'", .{@tagName(t)}, ), @@ -259,7 +259,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { ret_mcv: MCValue, fn_type: Type, arg_index: usize, - src: usize, + src_loc: Module.SrcLoc, stack_align: u32, /// Byte offset within the source file. @@ -428,7 +428,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { fn generateSymbol( bin_file: *link.File, - src: usize, + src_loc: Module.SrcLoc, typed_value: TypedValue, code: *std.ArrayList(u8), debug_output: DebugInfoOutput, @@ -450,19 +450,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { try branch_stack.append(.{}); const src_data: struct { lbrace_src: usize, rbrace_src: usize, source: []const u8 } = blk: { - if (module_fn.owner_decl.scope.cast(Module.Scope.Container)) |container_scope| { - const tree = container_scope.file_scope.contents.tree; - const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?; - const block = fn_proto.getBodyNode().?.castTag(.Block).?; - const lbrace_src = tree.token_locs[block.lbrace].start; - const rbrace_src = tree.token_locs[block.rbrace].start; - break :blk .{ .lbrace_src = lbrace_src, .rbrace_src = rbrace_src, .source = tree.source }; - } else if (module_fn.owner_decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| { - const byte_off = zir_module.contents.module.decls[module_fn.owner_decl.src_index].inst.src; - break :blk .{ .lbrace_src = byte_off, .rbrace_src = byte_off, .source = zir_module.source.bytes }; - } else { - unreachable; - } + const container_scope = module_fn.owner_decl.container; + const tree = container_scope.file_scope.contents.tree; + const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?; + const block = fn_proto.getBodyNode().?.castTag(.Block).?; + const lbrace_src = tree.token_locs[block.lbrace].start; + const rbrace_src = tree.token_locs[block.rbrace].start; + break :blk .{ + .lbrace_src = lbrace_src, + .rbrace_src = rbrace_src, + .source = tree.source, + }; }; var function = Self{ @@ -478,7 +476,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .fn_type = fn_type, .arg_index = 0, .branch_stack = &branch_stack, - .src = src, + .src_loc = src_loc, .stack_align = undefined, .prev_di_pc = 0, .prev_di_src = src_data.lbrace_src, @@ -489,7 +487,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { defer function.stack.deinit(bin_file.allocator); defer function.exitlude_jump_relocs.deinit(bin_file.allocator); - var call_info = function.resolveCallingConventionValues(src, fn_type) catch |err| switch (err) { + var call_info = function.resolveCallingConventionValues(src_loc.byte_offset, fn_type) catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, else => |e| return e, }; @@ -536,12 +534,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { const stack_end = self.max_end_stack; if (stack_end > math.maxInt(i32)) - return self.fail(self.src, "too much stack used in call parameters", .{}); + return self.failSymbol("too much stack used in call parameters", .{}); const aligned_stack_end = mem.alignForward(stack_end, self.stack_align); mem.writeIntLittle(u32, self.code.items[reloc_index..][0..4], @intCast(u32, aligned_stack_end)); if (self.code.items.len >= math.maxInt(i32)) { - return self.fail(self.src, "unable to perform relocation: jump too far", .{}); + return self.failSymbol("unable to perform relocation: jump too far", .{}); } if (self.exitlude_jump_relocs.items.len == 1) { self.code.items.len -= 5; @@ -598,7 +596,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { if (Instruction.Operand.fromU32(@intCast(u32, aligned_stack_end))) |op| { writeInt(u32, self.code.items[backpatch_reloc..][0..4], Instruction.sub(.al, .sp, .sp, op).toU32()); } else { - return self.fail(self.src, "TODO ARM: allow larger stacks", .{}); + return self.failSymbol("TODO ARM: allow larger stacks", .{}); } try self.dbgSetEpilogueBegin(); @@ -624,7 +622,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { if (math.cast(i26, amt)) |offset| { writeInt(u32, self.code.items[jmp_reloc..][0..4], Instruction.b(.al, offset).toU32()); } else |err| { - return self.fail(self.src, "exitlude jump is too large", .{}); + return self.failSymbol("exitlude jump is too large", .{}); } } } @@ -3678,7 +3676,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { fn fail(self: *Self, src: usize, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(self.err_msg == null); - self.err_msg = try ErrorMsg.create(self.bin_file.allocator, src, format, args); + self.err_msg = try ErrorMsg.create(self.bin_file.allocator, .{ + .file_scope = self.src_loc.file_scope, + .byte_offset = src, + }, format, args); + return error.CodegenFail; + } + + fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerError { + @setCold(true); + assert(self.err_msg == null); + self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args); return error.CodegenFail; } -- cgit v1.2.3