mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
stage2: add dbg_block_{begin,end} instruction
This commit is contained in:
parent
ad5770eba4
commit
a8520fbd0f
14 changed files with 119 additions and 1 deletions
|
|
@ -326,6 +326,10 @@ pub const Inst = struct {
|
||||||
/// Result type is always void.
|
/// Result type is always void.
|
||||||
/// Uses the `dbg_stmt` field.
|
/// Uses the `dbg_stmt` field.
|
||||||
dbg_stmt,
|
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.
|
/// Marks the start of an inline call.
|
||||||
/// Uses `ty_pl` with the payload being the index of a Value.Function in air.values.
|
/// Uses `ty_pl` with the payload being the index of a Value.Function in air.values.
|
||||||
dbg_inline_begin,
|
dbg_inline_begin,
|
||||||
|
|
@ -990,6 +994,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||||
.dbg_stmt,
|
.dbg_stmt,
|
||||||
.dbg_inline_begin,
|
.dbg_inline_begin,
|
||||||
.dbg_inline_end,
|
.dbg_inline_end,
|
||||||
|
.dbg_block_begin,
|
||||||
|
.dbg_block_end,
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
.store,
|
.store,
|
||||||
|
|
|
||||||
|
|
@ -2052,6 +2052,12 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
|
||||||
const tree = astgen.tree;
|
const tree = astgen.tree;
|
||||||
const node_tags = tree.nodes.items(.tag);
|
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);
|
var block_arena = std.heap.ArenaAllocator.init(gz.astgen.gpa);
|
||||||
defer block_arena.deinit();
|
defer block_arena.deinit();
|
||||||
const block_arena_allocator = block_arena.allocator();
|
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 genDefers(gz, parent_scope, scope, .normal_only);
|
||||||
try checkUsed(gz, parent_scope, scope);
|
try checkUsed(gz, parent_scope, scope);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -316,6 +316,8 @@ fn analyzeInst(
|
||||||
.dbg_stmt,
|
.dbg_stmt,
|
||||||
.dbg_inline_begin,
|
.dbg_inline_begin,
|
||||||
.dbg_inline_end,
|
.dbg_inline_end,
|
||||||
|
.dbg_block_begin,
|
||||||
|
.dbg_block_end,
|
||||||
.unreach,
|
.unreach,
|
||||||
.fence,
|
.fence,
|
||||||
.ret_addr,
|
.ret_addr,
|
||||||
|
|
|
||||||
26
src/Sema.zig
26
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_size => return sema.zirWasmMemorySize( block, extended),
|
||||||
.wasm_memory_grow => return sema.zirWasmMemoryGrow( block, extended),
|
.wasm_memory_grow => return sema.zirWasmMemoryGrow( block, extended),
|
||||||
.prefetch => return sema.zirPrefetch( 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
|
// 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(
|
fn zirDbgVar(
|
||||||
sema: *Sema,
|
sema: *Sema,
|
||||||
block: *Block,
|
block: *Block,
|
||||||
|
|
@ -5224,7 +5246,9 @@ fn emitDbgInline(
|
||||||
new_func_ty: Type,
|
new_func_ty: Type,
|
||||||
tag: Air.Inst.Tag,
|
tag: Air.Inst.Tag,
|
||||||
) CompileError!void {
|
) 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;
|
if (old_func == new_func) return;
|
||||||
|
|
||||||
try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func));
|
try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func));
|
||||||
|
|
|
||||||
|
|
@ -1646,6 +1646,10 @@ pub const Inst = struct {
|
||||||
/// The `@prefetch` builtin.
|
/// The `@prefetch` builtin.
|
||||||
/// `operand` is payload index to `BinNode`.
|
/// `operand` is payload index to `BinNode`.
|
||||||
prefetch,
|
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 {
|
pub const InstData = struct {
|
||||||
opcode: Extended,
|
opcode: Extended,
|
||||||
|
|
|
||||||
|
|
@ -654,6 +654,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.dbg_inline_end,
|
.dbg_inline_end,
|
||||||
=> try self.airDbgInline(inst),
|
=> try self.airDbgInline(inst),
|
||||||
|
|
||||||
|
.dbg_block_begin,
|
||||||
|
.dbg_block_end,
|
||||||
|
=> try self.airDbgBlock(inst),
|
||||||
|
|
||||||
.call => try self.airCall(inst, .auto),
|
.call => try self.airCall(inst, .auto),
|
||||||
.call_always_tail => try self.airCall(inst, .always_tail),
|
.call_always_tail => try self.airCall(inst, .always_tail),
|
||||||
.call_never_tail => try self.airCall(inst, .never_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 });
|
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 {
|
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
const name = self.air.nullTerminatedString(pl_op.payload);
|
||||||
|
|
|
||||||
|
|
@ -644,6 +644,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.dbg_inline_end,
|
.dbg_inline_end,
|
||||||
=> try self.airDbgInline(inst),
|
=> try self.airDbgInline(inst),
|
||||||
|
|
||||||
|
.dbg_block_begin,
|
||||||
|
.dbg_block_end,
|
||||||
|
=> try self.airDbgBlock(inst),
|
||||||
|
|
||||||
.call => try self.airCall(inst, .auto),
|
.call => try self.airCall(inst, .auto),
|
||||||
.call_always_tail => try self.airCall(inst, .always_tail),
|
.call_always_tail => try self.airCall(inst, .always_tail),
|
||||||
.call_never_tail => try self.airCall(inst, .never_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 });
|
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 {
|
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
const name = self.air.nullTerminatedString(pl_op.payload);
|
||||||
|
|
|
||||||
|
|
@ -618,6 +618,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.dbg_inline_end,
|
.dbg_inline_end,
|
||||||
=> try self.airDbgInline(inst),
|
=> try self.airDbgInline(inst),
|
||||||
|
|
||||||
|
.dbg_block_begin,
|
||||||
|
.dbg_block_end,
|
||||||
|
=> try self.airDbgBlock(inst),
|
||||||
|
|
||||||
.call => try self.airCall(inst, .auto),
|
.call => try self.airCall(inst, .auto),
|
||||||
.call_always_tail => try self.airCall(inst, .always_tail),
|
.call_always_tail => try self.airCall(inst, .always_tail),
|
||||||
.call_never_tail => try self.airCall(inst, .never_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 });
|
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 {
|
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
const name = self.air.nullTerminatedString(pl_op.payload);
|
||||||
|
|
|
||||||
|
|
@ -1330,6 +1330,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||||
.dbg_stmt,
|
.dbg_stmt,
|
||||||
.dbg_inline_begin,
|
.dbg_inline_begin,
|
||||||
.dbg_inline_end,
|
.dbg_inline_end,
|
||||||
|
.dbg_block_begin,
|
||||||
|
.dbg_block_end,
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
=> WValue.none,
|
=> WValue.none,
|
||||||
|
|
|
||||||
|
|
@ -735,6 +735,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||||
.dbg_inline_end,
|
.dbg_inline_end,
|
||||||
=> try self.airDbgInline(inst),
|
=> try self.airDbgInline(inst),
|
||||||
|
|
||||||
|
.dbg_block_begin,
|
||||||
|
.dbg_block_end,
|
||||||
|
=> try self.airDbgBlock(inst),
|
||||||
|
|
||||||
.call => try self.airCall(inst, .auto),
|
.call => try self.airCall(inst, .auto),
|
||||||
.call_always_tail => try self.airCall(inst, .always_tail),
|
.call_always_tail => try self.airCall(inst, .always_tail),
|
||||||
.call_never_tail => try self.airCall(inst, .never_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 });
|
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 {
|
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
const name = self.air.nullTerminatedString(pl_op.payload);
|
||||||
|
|
|
||||||
|
|
@ -1786,6 +1786,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
|
||||||
.dbg_inline_end,
|
.dbg_inline_end,
|
||||||
=> try airDbgInline(f, inst),
|
=> try airDbgInline(f, inst),
|
||||||
|
|
||||||
|
.dbg_block_begin,
|
||||||
|
.dbg_block_end,
|
||||||
|
=> CValue{ .none = {} },
|
||||||
|
|
||||||
.call => try airCall(f, inst, .auto),
|
.call => try airCall(f, inst, .auto),
|
||||||
.call_always_tail => try airCall(f, inst, .always_tail),
|
.call_always_tail => try airCall(f, inst, .always_tail),
|
||||||
.call_never_tail => try airCall(f, inst, .never_tail),
|
.call_never_tail => try airCall(f, inst, .never_tail),
|
||||||
|
|
|
||||||
|
|
@ -3220,6 +3220,10 @@ pub const FuncGen = struct {
|
||||||
/// Stack of locations where a call was inlined.
|
/// Stack of locations where a call was inlined.
|
||||||
dbg_inlined: std.ArrayListUnmanaged(DbgState) = .{},
|
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
|
/// 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.
|
/// in other instructions. This table is cleared before every function is generated.
|
||||||
func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, *const llvm.Value),
|
func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, *const llvm.Value),
|
||||||
|
|
@ -3254,6 +3258,7 @@ pub const FuncGen = struct {
|
||||||
fn deinit(self: *FuncGen) void {
|
fn deinit(self: *FuncGen) void {
|
||||||
self.builder.dispose();
|
self.builder.dispose();
|
||||||
self.dbg_inlined.deinit(self.gpa);
|
self.dbg_inlined.deinit(self.gpa);
|
||||||
|
self.dbg_block_stack.deinit(self.gpa);
|
||||||
self.func_inst_table.deinit(self.gpa);
|
self.func_inst_table.deinit(self.gpa);
|
||||||
self.blocks.deinit(self.gpa);
|
self.blocks.deinit(self.gpa);
|
||||||
}
|
}
|
||||||
|
|
@ -3475,6 +3480,8 @@ pub const FuncGen = struct {
|
||||||
.dbg_stmt => self.airDbgStmt(inst),
|
.dbg_stmt => self.airDbgStmt(inst),
|
||||||
.dbg_inline_begin => try self.airDbgInlineBegin(inst),
|
.dbg_inline_begin => try self.airDbgInlineBegin(inst),
|
||||||
.dbg_inline_end => try self.airDbgInlineEnd(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_ptr => try self.airDbgVarPtr(inst),
|
||||||
.dbg_var_val => try self.airDbgVarVal(inst),
|
.dbg_var_val => try self.airDbgVarVal(inst),
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
|
|
@ -4256,6 +4263,21 @@ pub const FuncGen = struct {
|
||||||
return null;
|
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 {
|
fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
||||||
const dib = self.dg.object.di_builder orelse return null;
|
const dib = self.dg.object.di_builder orelse return null;
|
||||||
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
|
||||||
|
|
|
||||||
|
|
@ -272,6 +272,8 @@ const Writer = struct {
|
||||||
.mul_with_overflow,
|
.mul_with_overflow,
|
||||||
.shl_with_overflow,
|
.shl_with_overflow,
|
||||||
=> try w.writeOverflow(s, inst),
|
=> try w.writeOverflow(s, inst),
|
||||||
|
|
||||||
|
.dbg_block_begin, .dbg_block_end => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -463,6 +463,10 @@ const Writer = struct {
|
||||||
.builtin_src,
|
.builtin_src,
|
||||||
=> try self.writeExtNode(stream, extended),
|
=> try self.writeExtNode(stream, extended),
|
||||||
|
|
||||||
|
.dbg_block_begin,
|
||||||
|
.dbg_block_end,
|
||||||
|
=> try stream.writeAll("))"),
|
||||||
|
|
||||||
.@"asm" => try self.writeAsm(stream, extended),
|
.@"asm" => try self.writeAsm(stream, extended),
|
||||||
.func => try self.writeFuncExtended(stream, extended),
|
.func => try self.writeFuncExtended(stream, extended),
|
||||||
.variable => try self.writeVarExtended(stream, extended),
|
.variable => try self.writeVarExtended(stream, extended),
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue