stage2: add dbg_block_{begin,end} instruction

This commit is contained in:
Veikka Tuominen 2022-03-18 12:31:22 +02:00
parent ad5770eba4
commit a8520fbd0f
14 changed files with 119 additions and 1 deletions

View file

@ -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,

View file

@ -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);
}

View file

@ -316,6 +316,8 @@ fn analyzeInst(
.dbg_stmt,
.dbg_inline_begin,
.dbg_inline_end,
.dbg_block_begin,
.dbg_block_end,
.unreach,
.fence,
.ret_addr,

View file

@ -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));

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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),

View file

@ -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;

View file

@ -272,6 +272,8 @@ const Writer = struct {
.mul_with_overflow,
.shl_with_overflow,
=> try w.writeOverflow(s, inst),
.dbg_block_begin, .dbg_block_end => {},
}
}

View file

@ -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),