authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-31 17:07:45+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-31 22:29:29-05:00
log627cf6ce482349c172150d058660f7a1646c2aac
treef786071370621bca7f51e95e4a35c626083b3de8
parentabbcf4032770676aee0e4a37f19d9e9ad2bdd992

astgen: clean up source line calculation and management

Clarify that `astgen.advanceSourceCursor` already increments absolute values of the line and columns numbers; i.e., `GenZir.calcLine` is thus not only obsolete but wrong by design. Incidentally, this clean up allows for specifying the `FnDecl` line numbers for DWARF use correctly as relative values with respect to the start of the parent `Decl`. This `Decl` in turn has its line number information specified relatively to its parent `Decl`, and so on, until we reach the global scope.

5 files changed, 70 insertions(+), 53 deletions(-)

src/AstGen.zig+44-45
......@@ -27,9 +27,11 @@ string_bytes: ArrayListUnmanaged(u8) = .{},
2727/// to avoid starting over the line/column scan for every declaration, which
2828/// would be O(N^2).
2929source_offset: u32 = 0,
30/// Tracks the current line of `source_offset`.
30/// Tracks the corresponding line of `source_offset`.
31/// This value is absolute.
3132source_line: u32 = 0,
32/// Tracks the current column of `source_offset`.
33/// Tracks the corresponding column of `source_offset`.
34/// This value is absolute.
3335source_column: u32 = 0,
3436/// Used for temporary allocations; freed after AstGen is complete.
3537/// The resulting ZIR code has no references to anything in this arena.
......@@ -2511,7 +2513,7 @@ fn makeDeferScope(
25112513 const token_starts = tree.tokens.items(.start);
25122514 const node_start = token_starts[tree.firstToken(expr_node)];
25132515 const defer_scope = try block_arena.create(Scope.Defer);
2514 astgen.advanceSourceCursor(tree.source, node_start);
2516 astgen.advanceSourceCursor(node_start);
25152517
25162518 defer_scope.* = .{
25172519 .base = .{ .tag = scope_tag },
......@@ -2775,14 +2777,9 @@ fn emitDbgNode(gz: *GenZir, node: Ast.Node.Index) !void {
27752777 if (gz.force_comptime) return;
27762778
27772779 const astgen = gz.astgen;
2778 const tree = astgen.tree;
2779 const source = tree.source;
2780 const token_starts = tree.tokens.items(.start);
2781 const node_start = token_starts[tree.firstToken(node)];
2782
2783 astgen.advanceSourceCursor(source, node_start);
2784 const line = @intCast(u32, astgen.source_line);
2785 const column = @intCast(u32, astgen.source_column);
2780 astgen.advanceSourceCursorToNode(node);
2781 const line = astgen.source_line - gz.decl_line;
2782 const column = astgen.source_column;
27862783
27872784 _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{
27882785 .dbg_stmt = .{
......@@ -3188,12 +3185,13 @@ fn fnDecl(
31883185 // We insert this at the beginning so that its instruction index marks the
31893186 // start of the top level declaration.
31903187 const block_inst = try gz.makeBlockInst(.block_inline, fn_proto.ast.proto_node);
3188 astgen.advanceSourceCursorToNode(decl_node);
31913189
31923190 var decl_gz: GenZir = .{
31933191 .force_comptime = true,
31943192 .in_defer = false,
31953193 .decl_node_index = fn_proto.ast.proto_node,
3196 .decl_line = gz.calcLine(decl_node),
3194 .decl_line = astgen.source_line,
31973195 .parent = scope,
31983196 .astgen = astgen,
31993197 .instructions = gz.instructions,
......@@ -3391,11 +3389,9 @@ fn fnDecl(
33913389 astgen.fn_block = &fn_gz;
33923390 defer astgen.fn_block = prev_fn_block;
33933391
3394 const token_starts = tree.tokens.items(.start);
3395 const lbrace_start = token_starts[tree.firstToken(body_node)];
3396 astgen.advanceSourceCursor(tree.source, lbrace_start);
3397 const lbrace_line = @intCast(u32, astgen.source_line);
3398 const lbrace_column = @intCast(u32, astgen.source_column);
3392 astgen.advanceSourceCursorToNode(body_node);
3393 const lbrace_line = astgen.source_line - decl_gz.decl_line;
3394 const lbrace_column = astgen.source_column;
33993395
34003396 _ = try expr(&fn_gz, params_scope, .none, body_node);
34013397 try checkUsed(gz, &fn_gz.base, params_scope);
......@@ -3465,11 +3461,12 @@ fn globalVarDecl(
34653461
34663462 const name_token = var_decl.ast.mut_token + 1;
34673463 const name_str_index = try astgen.identAsString(name_token);
3464 astgen.advanceSourceCursorToNode(node);
34683465
34693466 var block_scope: GenZir = .{
34703467 .parent = scope,
34713468 .decl_node_index = node,
3472 .decl_line = gz.calcLine(node),
3469 .decl_line = astgen.source_line,
34733470 .astgen = astgen,
34743471 .force_comptime = true,
34753472 .in_defer = false,
......@@ -3614,12 +3611,13 @@ fn comptimeDecl(
36143611 // top-level declaration.
36153612 const block_inst = try gz.makeBlockInst(.block_inline, node);
36163613 wip_members.nextDecl(false, false, false, false);
3614 astgen.advanceSourceCursorToNode(node);
36173615
36183616 var decl_block: GenZir = .{
36193617 .force_comptime = true,
36203618 .in_defer = false,
36213619 .decl_node_index = node,
3622 .decl_line = gz.calcLine(node),
3620 .decl_line = astgen.source_line,
36233621 .parent = scope,
36243622 .astgen = astgen,
36253623 .instructions = gz.instructions,
......@@ -3668,12 +3666,13 @@ fn usingnamespaceDecl(
36683666 // top-level declaration.
36693667 const block_inst = try gz.makeBlockInst(.block_inline, node);
36703668 wip_members.nextDecl(is_pub, true, false, false);
3669 astgen.advanceSourceCursorToNode(node);
36713670
36723671 var decl_block: GenZir = .{
36733672 .force_comptime = true,
36743673 .in_defer = false,
36753674 .decl_node_index = node,
3676 .decl_line = gz.calcLine(node),
3675 .decl_line = astgen.source_line,
36773676 .parent = scope,
36783677 .astgen = astgen,
36793678 .instructions = gz.instructions,
......@@ -3715,12 +3714,13 @@ fn testDecl(
37153714 const block_inst = try gz.makeBlockInst(.block_inline, node);
37163715
37173716 wip_members.nextDecl(false, false, false, false);
3717 astgen.advanceSourceCursorToNode(node);
37183718
37193719 var decl_block: GenZir = .{
37203720 .force_comptime = true,
37213721 .in_defer = false,
37223722 .decl_node_index = node,
3723 .decl_line = gz.calcLine(node),
3723 .decl_line = astgen.source_line,
37243724 .parent = scope,
37253725 .astgen = astgen,
37263726 .instructions = gz.instructions,
......@@ -3756,11 +3756,9 @@ fn testDecl(
37563756 astgen.fn_block = &fn_block;
37573757 defer astgen.fn_block = prev_fn_block;
37583758
3759 const token_starts = tree.tokens.items(.start);
3760 const lbrace_start = token_starts[tree.firstToken(body_node)];
3761 astgen.advanceSourceCursor(tree.source, lbrace_start);
3762 const lbrace_line = @intCast(u32, astgen.source_line);
3763 const lbrace_column = @intCast(u32, astgen.source_column);
3759 astgen.advanceSourceCursorToNode(body_node);
3760 const lbrace_line = astgen.source_line - decl_block.decl_line;
3761 const lbrace_column = astgen.source_column;
37643762
37653763 const block_result = try expr(&fn_block, &fn_block.base, .none, body_node);
37663764 if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) {
......@@ -3841,10 +3839,11 @@ fn structDeclInner(
38413839 // The struct_decl instruction introduces a scope in which the decls of the struct
38423840 // are in scope, so that field types, alignments, and default value expressions
38433841 // can refer to decls within the struct itself.
3842 astgen.advanceSourceCursorToNode(node);
38443843 var block_scope: GenZir = .{
38453844 .parent = &namespace.base,
38463845 .decl_node_index = node,
3847 .decl_line = gz.calcLine(node),
3846 .decl_line = astgen.source_line,
38483847 .astgen = astgen,
38493848 .force_comptime = true,
38503849 .in_defer = false,
......@@ -3966,10 +3965,11 @@ fn unionDeclInner(
39663965 // The union_decl instruction introduces a scope in which the decls of the union
39673966 // are in scope, so that field types, alignments, and default value expressions
39683967 // can refer to decls within the union itself.
3968 astgen.advanceSourceCursorToNode(node);
39693969 var block_scope: GenZir = .{
39703970 .parent = &namespace.base,
39713971 .decl_node_index = node,
3972 .decl_line = gz.calcLine(node),
3972 .decl_line = astgen.source_line,
39733973 .astgen = astgen,
39743974 .force_comptime = true,
39753975 .in_defer = false,
......@@ -4249,10 +4249,11 @@ fn containerDecl(
42494249
42504250 // The enum_decl instruction introduces a scope in which the decls of the enum
42514251 // are in scope, so that tag values can refer to decls within the enum itself.
4252 astgen.advanceSourceCursorToNode(node);
42524253 var block_scope: GenZir = .{
42534254 .parent = &namespace.base,
42544255 .decl_node_index = node,
4255 .decl_line = gz.calcLine(node),
4256 .decl_line = astgen.source_line,
42564257 .astgen = astgen,
42574258 .force_comptime = true,
42584259 .in_defer = false,
......@@ -6980,7 +6981,7 @@ fn builtinCall(
69806981 const token_starts = tree.tokens.items(.start);
69816982 const node_start = token_starts[tree.firstToken(node)];
69826983
6983 astgen.advanceSourceCursor(tree.source, node_start);
6984 astgen.advanceSourceCursor(node_start);
69846985
69856986 const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.LineColumn{
69866987 .line = @intCast(u32, astgen.source_line),
......@@ -9560,18 +9561,6 @@ const GenZir = struct {
95609561 return false;
95619562 }
95629563
9563 fn calcLine(gz: GenZir, node: Ast.Node.Index) u32 {
9564 const astgen = gz.astgen;
9565 const tree = astgen.tree;
9566 const source = tree.source;
9567 const token_starts = tree.tokens.items(.start);
9568 const node_start = token_starts[tree.firstToken(node)];
9569
9570 astgen.advanceSourceCursor(source, node_start);
9571
9572 return @intCast(u32, gz.decl_line + astgen.source_line);
9573 }
9574
95759564 fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) i32 {
95769565 return @bitCast(i32, node_index) - @bitCast(i32, gz.decl_node_index);
95779566 }
......@@ -9704,8 +9693,8 @@ const GenZir = struct {
97049693 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);
97059694 const block = node_datas[fn_decl].rhs;
97069695 const rbrace_start = token_starts[tree.lastToken(block)];
9707 astgen.advanceSourceCursor(tree.source, rbrace_start);
9708 const rbrace_line = @intCast(u32, astgen.source_line);
9696 astgen.advanceSourceCursor(rbrace_start);
9697 const rbrace_line = @intCast(u32, astgen.source_line - gz.decl_line);
97099698 const rbrace_column = @intCast(u32, astgen.source_column);
97109699
97119700 const columns = args.lbrace_column | (rbrace_column << 16);
......@@ -10736,7 +10725,17 @@ fn detectLocalShadowing(
1073610725 };
1073710726}
1073810727
10739fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void {
10728/// Advances the source cursor to the beginning of `node`.
10729fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void {
10730 const tree = astgen.tree;
10731 const token_starts = tree.tokens.items(.start);
10732 const node_start = token_starts[tree.firstToken(node)];
10733 astgen.advanceSourceCursor(node_start);
10734}
10735
10736/// Advances the source cursor to an absolute byte offset `end` in the file.
10737fn advanceSourceCursor(astgen: *AstGen, end: usize) void {
10738 const source = astgen.tree.source;
1074010739 var i = astgen.source_offset;
1074110740 var line = astgen.source_line;
1074210741 var column = astgen.source_column;
src/Module.zig+3-1
......@@ -375,6 +375,7 @@ pub const Decl = struct {
375375 src_node: Ast.Node.Index,
376376 /// Line number corresponding to `src_node`. Stored separately so that source files
377377 /// do not need to be loaded into memory in order to compute debug line numbers.
378 /// This value is absolute.
378379 src_line: u32,
379380 /// Index to ZIR `extra` array to the entry in the parent's decl structure
380381 /// (the part that says "for every decls_len"). The first item at this index is
......@@ -4122,7 +4123,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi
41224123 const has_linksection_or_addrspace = (flags & 0b1000) != 0;
41234124 // zig fmt: on
41244125
4125 const line = iter.parent_decl.relativeToLine(zir.extra[decl_sub_index + 4]);
4126 const line_off = zir.extra[decl_sub_index + 4];
4127 const line = iter.parent_decl.relativeToLine(line_off);
41264128 const decl_name_index = zir.extra[decl_sub_index + 5];
41274129 const decl_index = zir.extra[decl_sub_index + 6];
41284130 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;
src/Zir.zig+2-2
......@@ -2309,9 +2309,9 @@ pub const Inst = struct {
23092309 body_len: u32,
23102310
23112311 pub const SrcLocs = struct {
2312 /// Absolute line index in the source file.
2312 /// Line index in the source file relative to the parent decl.
23132313 lbrace_line: u32,
2314 /// Absolute line index in the source file.
2314 /// Line index in the source file relative to the parent decl.
23152315 rbrace_line: u32,
23162316 /// lbrace_column is least significant bits u16
23172317 /// rbrace_column is most significant bits u16
src/arch/x86_64/Emit.zig+4-1
......@@ -787,12 +787,14 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
787787 assert(tag == .dbg_line);
788788 const payload = emit.mir.instructions.items(.data)[inst].payload;
789789 const dbg_line_column = emit.mir.extraData(Mir.DbgLineColumn, payload).data;
790 log.debug("mirDbgLine", .{});
790791 try emit.dbgAdvancePCAndLine(dbg_line_column.line, dbg_line_column.column);
791792}
792793
793794fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
794795 const delta_line = @intCast(i32, line) - @intCast(i32, emit.prev_di_line);
795796 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;
797 log.debug(" (advance pc={d} and line={d})", .{ delta_line, delta_pc });
796798 switch (emit.debug_output) {
797799 .dwarf => |dbg_out| {
798800 // TODO Look into using the DWARF special opcodes to compress this data.
......@@ -806,7 +808,6 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
806808 leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable;
807809 }
808810 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy);
809 emit.prev_di_pc = emit.code.items.len;
810811 emit.prev_di_line = line;
811812 emit.prev_di_column = column;
812813 emit.prev_di_pc = emit.code.items.len;
......@@ -856,6 +857,7 @@ fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
856857 switch (emit.debug_output) {
857858 .dwarf => |dbg_out| {
858859 try dbg_out.dbg_line.append(DW.LNS.set_prologue_end);
860 log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column });
859861 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
860862 },
861863 .plan9 => {},
......@@ -869,6 +871,7 @@ fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
869871 switch (emit.debug_output) {
870872 .dwarf => |dbg_out| {
871873 try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin);
874 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column });
872875 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
873876 },
874877 .plan9 => {},
src/link/Elf.zig+17-4
......@@ -2507,7 +2507,13 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
25072507 defer deinitRelocs(self.base.allocator, &dbg_info_type_relocs);
25082508
25092509 const decl = func.owner_decl;
2510 const line_off = @intCast(u28, decl.src_line + func.lbrace_line);
2510 log.debug("updateFunc {s}{*}", .{ decl.name, func.owner_decl });
2511 log.debug(" (decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d})", .{
2512 decl.src_line,
2513 func.lbrace_line,
2514 func.rbrace_line,
2515 });
2516 const line = @intCast(u28, decl.src_line + func.lbrace_line);
25112517
25122518 const ptr_width_bytes = self.ptrWidthBytes();
25132519 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{
......@@ -2524,7 +2530,7 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
25242530 // to this function's begin curly.
25252531 assert(self.getRelocDbgLineOff() == dbg_line_buffer.items.len);
25262532 // Here we use a ULEB128-fixed-4 to make sure this field can be overwritten later.
2527 leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), line_off);
2533 leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), line);
25282534
25292535 dbg_line_buffer.appendAssumeCapacity(DW.LNS.set_file);
25302536 assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len);
......@@ -3070,15 +3076,22 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
30703076 const tracy = trace(@src());
30713077 defer tracy.end();
30723078
3079 log.debug("updateDeclLineNumber {s}{*}", .{ decl.name, decl });
3080
30733081 if (self.llvm_object) |_| return;
30743082
30753083 const func = decl.val.castTag(.function).?.data;
3076 const casted_line_off = @intCast(u28, decl.src_line + func.lbrace_line);
3084 log.debug(" (decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d})", .{
3085 decl.src_line,
3086 func.lbrace_line,
3087 func.rbrace_line,
3088 });
3089 const line = @intCast(u28, decl.src_line + func.lbrace_line);
30773090
30783091 const shdr = &self.sections.items[self.debug_line_section_index.?];
30793092 const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff();
30803093 var data: [4]u8 = undefined;
3081 leb128.writeUnsignedFixed(4, &data, casted_line_off);
3094 leb128.writeUnsignedFixed(4, &data, line);
30823095 try self.base.file.?.pwriteAll(&data, file_pos);
30833096}
30843097