From a8520fbd0f73c57d133c28c44d97e1173c6fe381 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 18 Mar 2022 12:31:22 +0200 Subject: [PATCH] stage2: add dbg_block_{begin,end} instruction --- src/Air.zig | 6 ++++++ src/AstGen.zig | 12 ++++++++++++ src/Liveness.zig | 2 ++ src/Sema.zig | 26 +++++++++++++++++++++++++- src/Zir.zig | 4 ++++ src/arch/aarch64/CodeGen.zig | 9 +++++++++ src/arch/arm/CodeGen.zig | 9 +++++++++ src/arch/riscv64/CodeGen.zig | 9 +++++++++ src/arch/wasm/CodeGen.zig | 2 ++ src/arch/x86_64/CodeGen.zig | 9 +++++++++ src/codegen/c.zig | 4 ++++ src/codegen/llvm.zig | 22 ++++++++++++++++++++++ src/print_air.zig | 2 ++ src/print_zir.zig | 4 ++++ 14 files changed, 119 insertions(+), 1 deletion(-) diff --git a/src/Air.zig b/src/Air.zig index 83a3bf1792511ef95011be6de66272f8222c265b..2d717f442d24e2085f9cc25c26f73e426aab5d94 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -326,6 +326,10 @@ pub const Inst = struct { /// Result type is always void. /// Uses the `dbg_stmt` field. dbg_stmt, + /// Marks the beginning of a semantic scope for debug info variables. + dbg_block_begin, + /// Marks the end of a semantic scope for debug info variables. + dbg_block_end, /// Marks the start of an inline call. /// Uses `ty_pl` with the payload being the index of a Value.Function in air.values. dbg_inline_begin, @@ -990,6 +994,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { .dbg_stmt, .dbg_inline_begin, .dbg_inline_end, + .dbg_block_begin, + .dbg_block_end, .dbg_var_ptr, .dbg_var_val, .store, diff --git a/src/AstGen.zig b/src/AstGen.zig index 742f13214c7bba2c4223785e22c73ae7696f97b7..ff11cb451c31cc8210e2fc6927b43397235d8b4a 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -2052,6 +2052,12 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod const tree = astgen.tree; const node_tags = tree.nodes.items(.tag); + _ = try gz.add(.{ .tag = .extended, .data = .{ .extended = .{ + .opcode = .dbg_block_begin, + .small = undefined, + .operand = undefined + } } }); + var block_arena = std.heap.ArenaAllocator.init(gz.astgen.gpa); defer block_arena.deinit(); const block_arena_allocator = block_arena.allocator(); @@ -2105,6 +2111,12 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod } } + _ = try gz.add(.{ .tag = .extended, .data = .{ .extended = .{ + .opcode = .dbg_block_end, + .small = undefined, + .operand = undefined + } } }); + try genDefers(gz, parent_scope, scope, .normal_only); try checkUsed(gz, parent_scope, scope); } diff --git a/src/Liveness.zig b/src/Liveness.zig index 5fd4bc2595910166f4ed7a95dba29f593dd6cc71..dd93d44f72ff1b9fcb1906d5afa3fd44c5c04eb9 100644 --- a/src/Liveness.zig +++ b/src/Liveness.zig @@ -316,6 +316,8 @@ fn analyzeInst( .dbg_stmt, .dbg_inline_begin, .dbg_inline_end, + .dbg_block_begin, + .dbg_block_end, .unreach, .fence, .ret_addr, diff --git a/src/Sema.zig b/src/Sema.zig index b798405d80ac88d00c6687ba378914f166415342..ae3eae013baa5343a1f5ea8f7e82ccb7de5d1e78 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1216,6 +1216,8 @@ fn zirExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .wasm_memory_size => return sema.zirWasmMemorySize( block, extended), .wasm_memory_grow => return sema.zirWasmMemoryGrow( block, extended), .prefetch => return sema.zirPrefetch( block, extended), + .dbg_block_begin => return sema.zirDbgBlockBegin( block), + .dbg_block_end => return sema.zirDbgBlockEnd( block), // zig fmt: on } } @@ -4215,6 +4217,26 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi }); } +fn zirDbgBlockBegin(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { + if (block.is_comptime or sema.mod.comp.bin_file.options.strip) return .void_value; + + _ = try block.addInst(.{ + .tag = .dbg_block_begin, + .data = undefined, + }); + return .void_value; +} + +fn zirDbgBlockEnd(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { + if (block.is_comptime or sema.mod.comp.bin_file.options.strip) return .void_value; + + _ = try block.addInst(.{ + .tag = .dbg_block_end, + .data = undefined, + }); + return .void_value; +} + fn zirDbgVar( sema: *Sema, block: *Block, @@ -5224,7 +5246,9 @@ fn emitDbgInline( new_func_ty: Type, tag: Air.Inst.Tag, ) CompileError!void { - // No change of file; no dbg_inline needed. + if (sema.mod.comp.bin_file.options.strip) return; + + // Recursive inline call; no dbg_inline needed. if (old_func == new_func) return; try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func)); diff --git a/src/Zir.zig b/src/Zir.zig index 8080ad9d417d0d6eb45e1723e835b75c0206fd99..f9b80c88ef76519e980dd1d316f105ac6aabe500 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -1646,6 +1646,10 @@ pub const Inst = struct { /// The `@prefetch` builtin. /// `operand` is payload index to `BinNode`. prefetch, + /// Marks the beginning of a semantic scope for debug info variables. + dbg_block_begin, + /// Marks the end of a semantic scope for debug info variables. + dbg_block_end, pub const InstData = struct { opcode: Extended, diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 3e63c59fe7c52a6965dc896ae8cf7bd585fcfb53..9a732e9fd0daf56979bf3a15dc84d22686c669ae 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -654,6 +654,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .dbg_inline_end, => try self.airDbgInline(inst), + .dbg_block_begin, + .dbg_block_end, + => try self.airDbgBlock(inst), + .call => try self.airCall(inst, .auto), .call_always_tail => try self.airCall(inst, .always_tail), .call_never_tail => try self.airCall(inst, .never_tail), @@ -2731,6 +2735,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, .dead, .{ .none, .none, .none }); } +fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { + // TODO emit debug info lexical block + return self.finishAir(inst, .dead, .{ .none, .none, .none }); +} + fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const name = self.air.nullTerminatedString(pl_op.payload); diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 82ab2b32a8ea7f990914dff1b0e78cf4c57bc7bb..921bc92c720a3cca2bd8fe83758557c83d9b3873 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -644,6 +644,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .dbg_inline_end, => try self.airDbgInline(inst), + .dbg_block_begin, + .dbg_block_end, + => try self.airDbgBlock(inst), + .call => try self.airCall(inst, .auto), .call_always_tail => try self.airCall(inst, .always_tail), .call_never_tail => try self.airCall(inst, .never_tail), @@ -2948,6 +2952,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, .dead, .{ .none, .none, .none }); } +fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { + // TODO emit debug info lexical block + return self.finishAir(inst, .dead, .{ .none, .none, .none }); +} + fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const name = self.air.nullTerminatedString(pl_op.payload); diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 80bdcd216ec79cdda0b6721edbff26872f525fea..4565322a5cb9bde5bfddaf2bdf995667a3a224ee 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -618,6 +618,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .dbg_inline_end, => try self.airDbgInline(inst), + .dbg_block_begin, + .dbg_block_end, + => try self.airDbgBlock(inst), + .call => try self.airCall(inst, .auto), .call_always_tail => try self.airCall(inst, .always_tail), .call_never_tail => try self.airCall(inst, .never_tail), @@ -1653,6 +1657,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, .dead, .{ .none, .none, .none }); } +fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { + // TODO emit debug info lexical block + return self.finishAir(inst, .dead, .{ .none, .none, .none }); +} + fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const name = self.air.nullTerminatedString(pl_op.payload); diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 685528c05d881644cbcc597d0c56d358976dd292..33e79587dfc29df7ef46ff2608aa39f1bdc0bde8 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1330,6 +1330,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .dbg_stmt, .dbg_inline_begin, .dbg_inline_end, + .dbg_block_begin, + .dbg_block_end, .dbg_var_ptr, .dbg_var_val, => WValue.none, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index df79ec990e5942f56bedc8347f290bf63ebc2540..d90ec90c2818ef3842217bfcb4ed2794d643ed31 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -735,6 +735,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .dbg_inline_end, => try self.airDbgInline(inst), + .dbg_block_begin, + .dbg_block_end, + => try self.airDbgBlock(inst), + .call => try self.airCall(inst, .auto), .call_always_tail => try self.airCall(inst, .always_tail), .call_never_tail => try self.airCall(inst, .never_tail), @@ -3683,6 +3687,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, .dead, .{ .none, .none, .none }); } +fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { + // TODO emit debug info lexical block + return self.finishAir(inst, .dead, .{ .none, .none, .none }); +} + fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const name = self.air.nullTerminatedString(pl_op.payload); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index b814be44453cb15877f85e0082d773f45512bb2c..88d26789cf68eddd86fd75703b8bd2181bc611f5 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1786,6 +1786,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .dbg_inline_end, => try airDbgInline(f, inst), + .dbg_block_begin, + .dbg_block_end, + => CValue{ .none = {} }, + .call => try airCall(f, inst, .auto), .call_always_tail => try airCall(f, inst, .always_tail), .call_never_tail => try airCall(f, inst, .never_tail), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 5a231ddc6e0ff9b248e5e655d2ff5c3872a6f90f..2d5b38eb1711259282b47797cfecb7b29fbfd421 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3220,6 +3220,10 @@ pub const FuncGen = struct { /// Stack of locations where a call was inlined. dbg_inlined: std.ArrayListUnmanaged(DbgState) = .{}, + /// Stack of `DILexicalBlock`s. dbg_block instructions cannot happend accross + /// dbg_inline instructions so no special handling there is required. + dbg_block_stack: std.ArrayListUnmanaged(*llvm.DIScope) = .{}, + /// This stores the LLVM values used in a function, such that they can be referred to /// in other instructions. This table is cleared before every function is generated. func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, *const llvm.Value), @@ -3254,6 +3258,7 @@ pub const FuncGen = struct { fn deinit(self: *FuncGen) void { self.builder.dispose(); self.dbg_inlined.deinit(self.gpa); + self.dbg_block_stack.deinit(self.gpa); self.func_inst_table.deinit(self.gpa); self.blocks.deinit(self.gpa); } @@ -3475,6 +3480,8 @@ pub const FuncGen = struct { .dbg_stmt => self.airDbgStmt(inst), .dbg_inline_begin => try self.airDbgInlineBegin(inst), .dbg_inline_end => try self.airDbgInlineEnd(inst), + .dbg_block_begin => try self.airDbgBlockBegin(), + .dbg_block_end => try self.airDbgBlockEnd(), .dbg_var_ptr => try self.airDbgVarPtr(inst), .dbg_var_val => try self.airDbgVarVal(inst), // zig fmt: on @@ -4256,6 +4263,21 @@ pub const FuncGen = struct { return null; } + fn airDbgBlockBegin(self: *FuncGen) !?*const llvm.Value { + const dib = self.dg.object.di_builder orelse return null; + const old_scope = self.di_scope.?; + try self.dbg_block_stack.append(self.gpa, old_scope); + const lexical_block = dib.createLexicalBlock(old_scope, self.di_file.?, self.prev_dbg_line, self.prev_dbg_column); + self.di_scope = lexical_block.toScope(); + return null; + } + + fn airDbgBlockEnd(self: *FuncGen) !?*const llvm.Value { + if (self.dg.object.di_builder == null) return null; + self.di_scope = self.dbg_block_stack.pop(); + return null; + } + fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { const dib = self.dg.object.di_builder orelse return null; const pl_op = self.air.instructions.items(.data)[inst].pl_op; diff --git a/src/print_air.zig b/src/print_air.zig index 0e7a02b4984f32c827c103d50bd96eb00fce5c58..294aed9e0797c8fac82dc8849da7827fa2f32365 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -272,6 +272,8 @@ const Writer = struct { .mul_with_overflow, .shl_with_overflow, => try w.writeOverflow(s, inst), + + .dbg_block_begin, .dbg_block_end => {}, } } diff --git a/src/print_zir.zig b/src/print_zir.zig index 8a4e8bbc2e314b40ea249099925f8ce6f1eb9361..12aad8698410ec9798b851128fc1ef6373c29241 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -463,6 +463,10 @@ const Writer = struct { .builtin_src, => try self.writeExtNode(stream, extended), + .dbg_block_begin, + .dbg_block_end, + => try stream.writeAll("))"), + .@"asm" => try self.writeAsm(stream, extended), .func => try self.writeFuncExtended(stream, extended), .variable => try self.writeVarExtended(stream, extended), -- 2.54.0