diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 841827cc194c1e9ce609bb51669ecbfbc89cbaf1..057b79f11c2c37ab30dfe88998e38d223ab70b31 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -43,6 +43,15 @@ pub fn findLineColumn(source: []const u8, byte_offset: usize) struct { line: usi return .{ .line = line, .column = column }; } +pub fn lineDelta(source: []const u8, start: usize, end: usize) usize { + var line: usize = 0; + for (source[start..end]) |byte| switch (byte) { + '\n' => line += 1, + else => continue, + }; + return line; +} + /// Returns the standard file system basename of a binary generated by the Zig compiler. pub fn binNameAlloc( allocator: *std.mem.Allocator, diff --git a/src-self-hosted/astgen.zig b/src-self-hosted/astgen.zig index 3f08d1272d941c1d53298ee814ec454d3051c324..029e7d4b8c2942f3956217db36ff6d52b67b154f 100644 --- a/src-self-hosted/astgen.zig +++ b/src-self-hosted/astgen.zig @@ -120,6 +120,8 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block var scope = parent_scope; for (block_node.statements()) |statement| { + const src = scope.tree().token_locs[statement.firstToken()].start; + _ = try addZIRNoOp(mod, scope, src, .dbg_stmt); switch (statement.tag) { .VarDecl => { const var_decl_node = statement.castTag(.VarDecl).?; @@ -146,7 +148,6 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block else => { const possibly_unused_result = try expr(mod, scope, .none, statement); if (!possibly_unused_result.tag.isNoReturn()) { - const src = scope.tree().token_locs[statement.firstToken()].start; _ = try addZIRUnOp(mod, scope, src, .ensure_result_used, possibly_unused_result); } }, diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig index 0114f663290f240bdcedb679895b76b4eefb14d4..1c441b91796297ac1e064fa523ae6152f31b850f 100644 --- a/src-self-hosted/codegen.zig +++ b/src-self-hosted/codegen.zig @@ -12,6 +12,11 @@ const ErrorMsg = Module.ErrorMsg; const Target = std.Target; const Allocator = mem.Allocator; const trace = @import("tracy.zig").trace; +const DW = std.dwarf; +const leb128 = std.debug.leb; + +// TODO Turn back on zig fmt when https://github.com/ziglang/zig/issues/5948 is implemented. +// zig fmt: off /// The codegen-related data that is stored in `ir.Inst.Block` instructions. pub const BlockData = struct { @@ -52,57 +57,57 @@ pub fn generateSymbol( switch (typed_value.ty.zigTypeTag()) { .Fn => { switch (bin_file.base.options.target.cpu.arch) { - //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code), - //.armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code), - //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code), - //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code), - //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code), - //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code), - //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code), - //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code), - //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code), - //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code), - //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code), - //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code), - //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code), - //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code), - //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code), - //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code), - //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code), - //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code), - //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code), - //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code), - //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code), - //.riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code), - //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code), - //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code), - //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code), - //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code), - //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code), - //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code), - //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code), - //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code), - //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code), - .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code), - //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code), - //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code), - //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code), - //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code), - //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code), - //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code), - //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code), - //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code), - //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code), - //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code), - //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code), - //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code), - //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code), - //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code), - //.wasm32 => return Function(.wasm32).generateSymbol(bin_file, src, typed_value, code), - //.wasm64 => return Function(.wasm64).generateSymbol(bin_file, src, typed_value, code), - //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code), - //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code), - //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code), + //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code, dbg_line), + .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.wasm32 => return Function(.wasm32).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.wasm64 => return Function(.wasm64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code, dbg_line), + //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code, dbg_line), 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."), } }, @@ -207,6 +212,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { target: *const std.Target, mod_fn: *const Module.Fn, code: *std.ArrayList(u8), + dbg_line: *std.ArrayList(u8), err_msg: ?*ErrorMsg, args: []MCValue, ret_mcv: MCValue, @@ -215,6 +221,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { src: usize, stack_align: u32, + /// Byte offset within the source file. + prev_di_src: usize, + /// Relative to the beginning of `code`. + prev_di_pc: usize, + /// Used to find newlines and count line deltas. + source: []const u8, + /// Byte offset within the source file of the ending curly. + rbrace_src: usize, + /// The value is an offset into the `Function` `code` from the beginning. /// To perform the reloc, write 32-bit signed little-endian integer /// which is a relative jump, based on the address following the reloc. @@ -366,6 +381,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { src: usize, typed_value: TypedValue, code: *std.ArrayList(u8), + dbg_line: *std.ArrayList(u8), ) GenerateSymbolError!Result { const module_fn = typed_value.val.cast(Value.Payload.Function).?.func; @@ -380,12 +396,20 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { const branch = try branch_stack.addOne(); branch.* = .{}; + const scope_file = module_fn.owner_decl.scope.cast(Module.Scope.File).?; + const tree = scope_file.contents.tree; + const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?; + const block = fn_proto.body().?.castTag(.Block).?; + const lbrace_src = tree.token_locs[block.lbrace].start; + const rbrace_src = tree.token_locs[block.rbrace].start; + var function = Self{ .gpa = bin_file.allocator, .target = &bin_file.base.options.target, .bin_file = bin_file, .mod_fn = module_fn, .code = code, + .dbg_line = dbg_line, .err_msg = null, .args = undefined, // populated after `resolveCallingConventionValues` .ret_mcv = undefined, // populated after `resolveCallingConventionValues` @@ -394,6 +418,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .branch_stack = &branch_stack, .src = src, .stack_align = undefined, + .prev_di_pc = 0, + .prev_di_src = lbrace_src, + .rbrace_src = rbrace_src, + .source = tree.source, }; defer function.exitlude_jump_relocs.deinit(bin_file.allocator); @@ -432,21 +460,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { // TODO During semantic analysis, check if there are no function calls. If there // are none, here we can omit the part where we subtract and then add rsp. self.code.appendSliceAssumeCapacity(&[_]u8{ - // push rbp - 0x55, - // mov rbp, rsp - 0x48, - 0x89, - 0xe5, - // sub rsp, imm32 (with reloc) - 0x48, - 0x81, - 0xec, + 0x55, // push rbp + 0x48, 0x89, 0xe5, // mov rbp, rsp + 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc) }); const reloc_index = self.code.items.len; self.code.items.len += 4; + try self.dbgSetPrologueEnd(); try self.genBody(self.mod_fn.analysis.success); + try self.dbgSetEpilogueBegin(); const stack_end = self.branch_stack.items[0].max_end_stack; if (stack_end > math.maxInt(i32)) @@ -486,13 +509,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { 0xc3, // ret }); } else { + try self.dbgSetPrologueEnd(); try self.genBody(self.mod_fn.analysis.success); + try self.dbgSetEpilogueBegin(); } }, else => { + try self.dbgSetPrologueEnd(); try self.genBody(self.mod_fn.analysis.success); + try self.dbgSetEpilogueBegin(); }, } + // Drop them off at the rbrace. + try self.dbgAdvancePCAndLine(self.rbrace_src); } fn genBody(self: *Self, body: ir.Body) InnerError!void { @@ -509,6 +538,38 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { } } + fn dbgSetPrologueEnd(self: *Self) InnerError!void { + try self.dbg_line.append(DW.LNS_set_prologue_end); + try self.dbgAdvancePCAndLine(self.prev_di_src); + } + + fn dbgSetEpilogueBegin(self: *Self) InnerError!void { + try self.dbg_line.append(DW.LNS_set_epilogue_begin); + try self.dbgAdvancePCAndLine(self.prev_di_src); + } + + fn dbgAdvancePCAndLine(self: *Self, src: usize) InnerError!void { + // TODO Look into improving the performance here by adding a token-index-to-line + // lookup table, and changing ir.Inst from storing byte offset to token. Currently + // this involves scanning over the source code for newlines + // (but only from the previous byte offset to the new one). + const delta_line = std.zig.lineDelta(self.source, self.prev_di_src, src); + const delta_pc = self.code.items.len - self.prev_di_pc; + self.prev_di_src = src; + self.prev_di_pc = self.code.items.len; + // TODO Look into using the DWARF special opcodes to compress this data. It lets you emit + // single-byte opcodes that add different numbers to both the PC and the line number + // at the same time. + try self.dbg_line.ensureCapacity(self.dbg_line.items.len + 11); + self.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc); + leb128.writeULEB128(self.dbg_line.writer(), delta_pc) catch unreachable; + if (delta_line != 0) { + self.dbg_line.appendAssumeCapacity(DW.LNS_advance_line); + leb128.writeULEB128(self.dbg_line.writer(), delta_line) catch unreachable; + } + self.dbg_line.appendAssumeCapacity(DW.LNS_copy); + } + fn processDeath(self: *Self, inst: *ir.Inst) void { const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; const entry = branch.inst_table.getEntry(inst) orelse return; @@ -544,6 +605,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .cmp_neq => return self.genCmp(inst.castTag(.cmp_neq).?, .neq), .condbr => return self.genCondBr(inst.castTag(.condbr).?), .constant => unreachable, // excluded from function bodies + .dbg_stmt => return self.genDbgStmt(inst.castTag(.dbg_stmt).?), .floatcast => return self.genFloatCast(inst.castTag(.floatcast).?), .intcast => return self.genIntCast(inst.castTag(.intcast).?), .isnonnull => return self.genIsNonNull(inst.castTag(.isnonnull).?), @@ -1107,6 +1169,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { } } + fn genDbgStmt(self: *Self, inst: *ir.Inst.NoOp) !MCValue { + try self.dbgAdvancePCAndLine(inst.base.src); + return MCValue.none; + } + fn genCondBr(self: *Self, inst: *ir.Inst.CondBr) !MCValue { switch (arch) { .x86_64 => { diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index deb0a91cec193bd9616bf4603eafd5b6112b07b0..1188230a54304a66d4f34c3ccc009bea8a776a76 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -65,6 +65,7 @@ pub const Inst = struct { cmp_neq, condbr, constant, + dbg_stmt, isnonnull, isnull, /// Read a value from a pointer. @@ -88,6 +89,7 @@ pub const Inst = struct { .unreach, .arg, .breakpoint, + .dbg_stmt, => NoOp, .ref, diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 284b881028fb855441e7d96b03dfff7133c8710c..c680bb47d53543f28fc7bc371d6151edb4a89a35 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -2024,9 +2024,9 @@ pub const File = struct { // line number of the open curly from the beginning of the file. const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?; const block = fn_proto.body().?.castTag(.Block).?; - const loc = tree.tokenLocation(0, block.lbrace); + const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start); // No need to add one; this is a delta from DWARF's starting line number (1). - break :blk @intCast(u28, loc.line); + break :blk @intCast(u28, line_delta); } else { const prev_src_fn = src_file.fns.entries.items[src_fn_index - 1].key; const mod_fn = @fieldParentPtr(Module.Fn, "link", prev_src_fn); @@ -2035,9 +2035,12 @@ pub const File = struct { const prev_block = prev_fn_proto.body().?.castTag(.Block).?; const this_block = this_fn_proto.body().?.castTag(.Block).?; // Find the difference between prev decl end curly and this decl begin curly. - const loc = tree.tokenLocation(tree.token_locs[prev_block.rbrace].start, this_block.lbrace); + const line_delta = std.zig.lineDelta(tree.source, + tree.token_locs[prev_block.rbrace].start, + tree.token_locs[this_block.lbrace].start, + ); // No need to add one; this is a delta from the previous line number. - break :blk @intCast(u28, loc.line); + break :blk @intCast(u28, line_delta); } }; diff --git a/src-self-hosted/zir.zig b/src-self-hosted/zir.zig index 318c4bdc8eee8421962c6a751d3abead26477694..5fb81df051ecb66950ce9ed2ae2de8c605b2d49f 100644 --- a/src-self-hosted/zir.zig +++ b/src-self-hosted/zir.zig @@ -107,6 +107,8 @@ pub const Inst = struct { condbr, /// Special case, has no textual representation. @"const", + /// Declares the beginning of a statement. Used for debug info. + dbg_stmt, /// Represents a pointer to a global decl by name. declref, /// Represents a pointer to a global decl by string name. @@ -211,6 +213,7 @@ pub const Inst = struct { return switch (tag) { .arg, .breakpoint, + .dbg_stmt, .returnvoid, .alloc_inferred, .ret_ptr, @@ -324,6 +327,7 @@ pub const Inst = struct { .coerce_result_block_ptr, .coerce_to_ptr_elem, .@"const", + .dbg_stmt, .declref, .declref_str, .declval, @@ -1843,6 +1847,7 @@ const EmitZIR = struct { .breakpoint => try self.emitNoOp(inst.src, .breakpoint), .unreach => try self.emitNoOp(inst.src, .@"unreachable"), .retvoid => try self.emitNoOp(inst.src, .returnvoid), + .dbg_stmt => try self.emitNoOp(inst.src, .dbg_stmt), .not => try self.emitUnOp(inst.src, new_body, inst.castTag(.not).?, .boolnot), .ret => try self.emitUnOp(inst.src, new_body, inst.castTag(.ret).?, .@"return"), diff --git a/src-self-hosted/zir_sema.zig b/src-self-hosted/zir_sema.zig index 6bd4159e36ee33429e46e013c3559c24f5c2bf6a..f2ed8abeaca3affaf7e4a5f89e156a90d7ed5876 100644 --- a/src-self-hosted/zir_sema.zig +++ b/src-self-hosted/zir_sema.zig @@ -41,6 +41,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! .coerce_to_ptr_elem => return analyzeInstCoerceToPtrElem(mod, scope, old_inst.castTag(.coerce_to_ptr_elem).?), .compileerror => return analyzeInstCompileError(mod, scope, old_inst.castTag(.compileerror).?), .@"const" => return analyzeInstConst(mod, scope, old_inst.castTag(.@"const").?), + .dbg_stmt => return analyzeInstDbgStmt(mod, scope, old_inst.castTag(.dbg_stmt).?), .declref => return analyzeInstDeclRef(mod, scope, old_inst.castTag(.declref).?), .declref_str => return analyzeInstDeclRefStr(mod, scope, old_inst.castTag(.declref_str).?), .declval => return analyzeInstDeclVal(mod, scope, old_inst.castTag(.declval).?), @@ -487,6 +488,11 @@ fn analyzeInstBreakVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.BreakVoid) return analyzeBreak(mod, scope, inst.base.src, block, void_inst); } +fn analyzeInstDbgStmt(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { + const b = try mod.requireRuntimeBlock(scope, inst.base.src); + return mod.addNoOp(b, inst.base.src, Type.initTag(.void), .dbg_stmt); +} + fn analyzeInstDeclRefStr(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRefStr) InnerError!*Inst { const decl_name = try resolveConstString(mod, scope, inst.positionals.name); return mod.analyzeDeclRefByName(scope, inst.base.src, decl_name);