Commit a8520fbd0f

Veikka Tuominen <git@vexu.eu>
2022-03-18 11:31:22
stage2: add dbg_block_{begin,end} instruction
1 parent ad5770e
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);
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);
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);
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,
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);
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),
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;
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,
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);
 }
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,
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 => {},
         }
     }
 
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),
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));
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,