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 83a3bf1792..2d717f442d 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 742f13214c..ff11cb451c 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 5fd4bc2595..dd93d44f72 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 b798405d80..ae3eae013b 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 8080ad9d41..f9b80c88ef 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 3e63c59fe7..9a732e9fd0 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 82ab2b32a8..921bc92c72 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 80bdcd216e..4565322a5c 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 685528c05d..33e79587df 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 df79ec990e..d90ec90c28 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 b814be4445..88d26789cf 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 5a231ddc6e..2d5b38eb17 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 0e7a02b498..294aed9e07 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 8a4e8bbc2e..12aad86984 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),