Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stage2: add debug info for locals in the LLVM backend #11145

Merged
merged 1 commit into from
Mar 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions src/Air.zig
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,15 @@ pub const Inst = struct {
/// Result type is always void.
/// Uses the `dbg_stmt` field.
dbg_stmt,
/// Marks the beginning of a local variable. The operand is a pointer pointing
/// to the storage for the variable. The local may be a const or a var.
/// Result type is always void.
/// Uses `pl_op`. The payload index is the variable name. It points to the extra
/// array, reinterpreting the bytes there as a null-terminated string.
dbg_var_ptr,
/// Same as `dbg_var_ptr` except the local is a const, not a var, and the
/// operand is the local's value.
dbg_var_val,
/// ?T => bool
/// Result type is always bool.
/// Uses the `un_op` field.
Expand Down Expand Up @@ -962,6 +971,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {

.breakpoint,
.dbg_stmt,
.dbg_var_ptr,
.dbg_var_val,
.store,
.fence,
.atomic_store_unordered,
Expand All @@ -972,13 +983,13 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.memcpy,
.set_union_tag,
.prefetch,
=> return Type.initTag(.void),
=> return Type.void,

.ptrtoint,
.slice_len,
.ret_addr,
.frame_addr,
=> return Type.initTag(.usize),
=> return Type.usize,

.wasm_memory_grow => return Type.i32,
.wasm_memory_size => return Type.u32,
Expand Down Expand Up @@ -1089,3 +1100,12 @@ pub fn value(air: Air, inst: Air.Inst.Ref) ?Value {
else => return air.typeOfIndex(inst_index).onePossibleValue(),
}
}

pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {
const bytes = std.mem.sliceAsBytes(air.extra[index..]);
var end: usize = 0;
while (bytes[end] != 0) {
end += 1;
}
return bytes[0..end :0];
}
40 changes: 40 additions & 0 deletions src/AstGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2389,6 +2389,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.breakpoint,
.fence,
.dbg_stmt,
.dbg_var_ptr,
.dbg_var_val,
.ensure_result_used,
.ensure_result_non_error,
.@"export",
Expand Down Expand Up @@ -2666,6 +2668,15 @@ fn varDecl(
} else .none;
const init_inst = try reachableExpr(gz, scope, result_loc, var_decl.ast.init_node, node);

if (!gz.force_comptime) {
_ = try gz.add(.{ .tag = .dbg_var_val, .data = .{
.str_op = .{
.str = ident_name,
.operand = init_inst,
},
} });
}

const sub_scope = try block_arena.create(Scope.LocalVal);
sub_scope.* = .{
.parent = scope,
Expand Down Expand Up @@ -2751,6 +2762,15 @@ fn varDecl(
}
gz.instructions.items.len = dst;

if (!gz.force_comptime) {
_ = try gz.add(.{ .tag = .dbg_var_val, .data = .{
.str_op = .{
.str = ident_name,
.operand = init_inst,
},
} });
}

const sub_scope = try block_arena.create(Scope.LocalVal);
sub_scope.* = .{
.parent = scope,
Expand Down Expand Up @@ -2785,6 +2805,16 @@ fn varDecl(
_ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
}
const const_ptr = try gz.addUnNode(.make_ptr_const, init_scope.rl_ptr, node);

if (!gz.force_comptime) {
_ = try gz.add(.{ .tag = .dbg_var_ptr, .data = .{
.str_op = .{
.str = ident_name,
.operand = const_ptr,
},
} });
}

const sub_scope = try block_arena.create(Scope.LocalPtr);
sub_scope.* = .{
.parent = scope,
Expand Down Expand Up @@ -2848,6 +2878,16 @@ fn varDecl(
if (resolve_inferred_alloc != .none) {
_ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
}

if (!gz.force_comptime) {
_ = try gz.add(.{ .tag = .dbg_var_ptr, .data = .{
.str_op = .{
.str = ident_name,
.operand = var_data.alloc,
},
} });
}

const sub_scope = try block_arena.create(Scope.LocalPtr);
sub_scope.* = .{
.parent = scope,
Expand Down
7 changes: 7 additions & 0 deletions src/Liveness.zig
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,13 @@ fn analyzeInst(
return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none });
},

.dbg_var_ptr,
.dbg_var_val,
=> {
const operand = inst_datas[inst].pl_op.operand;
return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none });
},

.prefetch => {
const prefetch = inst_datas[inst].prefetch;
return trackOperands(a, new_set, inst, main_tomb, .{ prefetch.ptr, .none, .none });
Expand Down
47 changes: 43 additions & 4 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,16 @@ fn analyzeBodyInner(
i += 1;
continue;
},
.dbg_var_ptr => {
try sema.zirDbgVar(block, inst, .dbg_var_ptr);
i += 1;
continue;
},
.dbg_var_val => {
try sema.zirDbgVar(block, inst, .dbg_var_val);
i += 1;
continue;
},
.ensure_err_payload_void => {
try sema.zirEnsureErrPayloadVoid(block, inst);
i += 1;
Expand Down Expand Up @@ -4158,14 +4168,11 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError
}

fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
const tracy = trace(@src());
defer tracy.end();

// We do not set sema.src here because dbg_stmt instructions are only emitted for
// ZIR code that possibly will need to generate runtime code. So error messages
// and other source locations must not rely on sema.src being set from dbg_stmt
// instructions.
if (block.is_comptime) return;
if (block.is_comptime or sema.mod.comp.bin_file.options.strip) return;

const inst_data = sema.code.instructions.items(.data)[inst].dbg_stmt;
_ = try block.addInst(.{
Expand All @@ -4177,6 +4184,38 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi
});
}

fn zirDbgVar(
sema: *Sema,
block: *Block,
inst: Zir.Inst.Index,
air_tag: Air.Inst.Tag,
) CompileError!void {
if (block.is_comptime or sema.mod.comp.bin_file.options.strip) return;

const str_op = sema.code.instructions.items(.data)[inst].str_op;
const operand = sema.resolveInst(str_op.operand);
const operand_ty = sema.typeOf(operand);
if (!(try sema.typeHasRuntimeBits(block, sema.src, operand_ty))) return;
const name = str_op.getStr(sema.code);

// Add the name to the AIR.
const name_extra_index = @intCast(u32, sema.air_extra.items.len);
const elements_used = name.len / 4 + 1;
try sema.air_extra.ensureUnusedCapacity(sema.gpa, elements_used);
const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());
mem.copy(u8, buffer, name);
buffer[name.len] = 0;
sema.air_extra.items.len += elements_used;

_ = try block.addInst(.{
.tag = air_tag,
.data = .{ .pl_op = .{
.payload = name_extra_index,
.operand = operand,
} },
});
}

fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
const src = inst_data.src();
Expand Down
22 changes: 22 additions & 0 deletions src/Zir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,14 @@ pub const Inst = struct {
/// Uses the `dbg_stmt` union field. The line and column are offset
/// from the parent declaration.
dbg_stmt,
/// Marks a variable declaration. Used for debug info.
/// Uses the `str_op` union field. The string is the local variable name,
/// and the operand is the pointer to the variable's location. The local
/// may be a const or a var.
dbg_var_ptr,
/// Same as `dbg_var_ptr` but the local is always a const and the operand
/// is the local's value.
dbg_var_val,
/// Uses a name to identify a Decl and takes a pointer to it.
/// Uses the `str_tok` union field.
decl_ref,
Expand Down Expand Up @@ -1032,6 +1040,8 @@ pub const Inst = struct {
.error_set_decl_anon,
.error_set_decl_func,
.dbg_stmt,
.dbg_var_ptr,
.dbg_var_val,
.decl_ref,
.decl_val,
.load,
Expand Down Expand Up @@ -1297,6 +1307,8 @@ pub const Inst = struct {
.error_set_decl_anon = .pl_node,
.error_set_decl_func = .pl_node,
.dbg_stmt = .dbg_stmt,
.dbg_var_ptr = .str_op,
.dbg_var_val = .str_op,
.decl_ref = .str_tok,
.decl_val = .str_tok,
.load = .un_node,
Expand Down Expand Up @@ -2232,6 +2244,15 @@ pub const Inst = struct {
return .{ .node_offset = self.src_node };
}
},
str_op: struct {
/// Offset into `string_bytes`. Null-terminated.
str: u32,
operand: Ref,

pub fn getStr(self: @This(), zir: Zir) [:0]const u8 {
return zir.nullTerminatedString(self.str);
}
},

// Make sure we don't accidentally add a field to make this union
// bigger than expected. Note that in Debug builds, Zig is allowed
Expand Down Expand Up @@ -2268,6 +2289,7 @@ pub const Inst = struct {
switch_capture,
dbg_stmt,
inst_node,
str_op,
};
};

Expand Down
13 changes: 13 additions & 0 deletions src/arch/aarch64/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.prefetch => try self.airPrefetch(inst),
.mul_add => try self.airMulAdd(inst),

.dbg_var_ptr,
.dbg_var_val,
=> try self.airDbgVar(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),
Expand Down Expand Up @@ -2650,6 +2654,15 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAirBookkeeping();
}

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);
const operand = pl_op.operand;
// TODO emit debug info for this variable
_ = name;
return self.finishAir(inst, .dead, .{ operand, .none, .none });
}

fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
const cond = try self.resolveInst(pl_op.operand);
Expand Down
13 changes: 13 additions & 0 deletions src/arch/arm/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.prefetch => try self.airPrefetch(inst),
.mul_add => try self.airMulAdd(inst),

.dbg_var_ptr,
.dbg_var_val,
=> try self.airDbgVar(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),
Expand Down Expand Up @@ -2831,6 +2835,15 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAirBookkeeping();
}

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);
const operand = pl_op.operand;
// TODO emit debug info for this variable
_ = name;
return self.finishAir(inst, .dead, .{ operand, .none, .none });
}

fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
const cond = try self.resolveInst(pl_op.operand);
Expand Down
13 changes: 13 additions & 0 deletions src/arch/riscv64/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.prefetch => try self.airPrefetch(inst),
.mul_add => try self.airMulAdd(inst),

.dbg_var_ptr,
.dbg_var_val,
=> try self.airDbgVar(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),
Expand Down Expand Up @@ -1636,6 +1640,15 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAirBookkeeping();
}

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);
const operand = pl_op.operand;
// TODO emit debug info for this variable
_ = name;
return self.finishAir(inst, .dead, .{ operand, .none, .none });
}

fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
_ = inst;

Expand Down
7 changes: 6 additions & 1 deletion src/arch/wasm/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1219,13 +1219,18 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.br => self.airBr(inst),
.bool_to_int => self.airBoolToInt(inst),
.cond_br => self.airCondBr(inst),
.dbg_stmt => WValue.none,
.intcast => self.airIntcast(inst),
.fptrunc => self.airFptrunc(inst),
.fpext => self.airFpext(inst),
.float_to_int => self.airFloatToInt(inst),
.get_union_tag => self.airGetUnionTag(inst),

// TODO
.dbg_stmt,
.dbg_var_ptr,
.dbg_var_val,
=> WValue.none,

.call => self.airCall(inst, .auto),
.call_always_tail => self.airCall(inst, .always_tail),
.call_never_tail => self.airCall(inst, .never_tail),
Expand Down
13 changes: 13 additions & 0 deletions src/arch/x86_64/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.prefetch => try self.airPrefetch(inst),
.mul_add => try self.airMulAdd(inst),

.dbg_var_ptr,
.dbg_var_val,
=> try self.airDbgVar(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),
Expand Down Expand Up @@ -3666,6 +3670,15 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAirBookkeeping();
}

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);
const operand = pl_op.operand;
// TODO emit debug info for this variable
_ = name;
return self.finishAir(inst, .dead, .{ operand, .none, .none });
}

fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {
const abi_size = ty.abiSize(self.target.*);
switch (mcv) {
Expand Down
Loading